forked from pool/util-linux
This commit is contained in:
parent
f70a59e749
commit
6e24cd613b
@ -1,245 +0,0 @@
|
|||||||
commit 2368077223fa5800cf88659c9c57a7f6517f3fad
|
|
||||||
Author: Karel Zak <kzak@redhat.com>
|
|
||||||
Date: Tue Sep 11 14:35:34 2007 +0200
|
|
||||||
|
|
||||||
mount: prevent loop mounting the same file twice
|
|
||||||
|
|
||||||
The mount syscall prevents mounting the same device twice
|
|
||||||
to the same mountpoint. When loop mounting a file, for each
|
|
||||||
file a new loop device gets allocated, which prevents the detection
|
|
||||||
of loop mounting the same file to the same mountpoint twice.
|
|
||||||
The patch adds a check to prevent double mounts, if the same loopfile
|
|
||||||
is going to be mounted with the same offset to the same mountpoint.
|
|
||||||
|
|
||||||
Co-Author: Matthias Koenig <mkoenig@suse.de>
|
|
||||||
Signed-off-by: Matthias Koenig <mkoenig@suse.de>
|
|
||||||
Signed-off-by: Karel Zak <kzak@redhat.com>
|
|
||||||
|
|
||||||
Index: util-linux-ng-2.13.1/mount/lomount.c
|
|
||||||
===================================================================
|
|
||||||
--- util-linux-ng-2.13.1.orig/mount/lomount.c
|
|
||||||
+++ util-linux-ng-2.13.1/mount/lomount.c
|
|
||||||
@@ -143,7 +143,7 @@ show_used_loop_devices (void) {
|
|
||||||
|
|
||||||
for (j = 0; j < SIZE(loop_formats); j++) {
|
|
||||||
for(i = 0; i < 256; i++) {
|
|
||||||
- sprintf(dev, loop_formats[j], i);
|
|
||||||
+ snprintf(dev, sizeof(dev), loop_formats[j], i);
|
|
||||||
if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
|
|
||||||
fd = open (dev, O_RDONLY);
|
|
||||||
if (fd >= 0) {
|
|
||||||
@@ -169,6 +169,102 @@ show_used_loop_devices (void) {
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+/* check if the loopfile is already associated with the same given
|
|
||||||
+ * parameters.
|
|
||||||
+ *
|
|
||||||
+ * returns: -1 error
|
|
||||||
+ * 0 unused
|
|
||||||
+ * 1 loop device already used
|
|
||||||
+ */
|
|
||||||
+static int
|
|
||||||
+is_associated(int dev, struct stat *file, unsigned long long offset)
|
|
||||||
+{
|
|
||||||
+ struct loop_info64 linfo64;
|
|
||||||
+ struct loop_info64 linfo;
|
|
||||||
+ int ret = 0;
|
|
||||||
+
|
|
||||||
+ if (ioctl(dev, LOOP_GET_STATUS64, &linfo64) == 0) {
|
|
||||||
+ if (file->st_dev == linfo64.lo_device &&
|
|
||||||
+ file->st_ino == linfo64.lo_inode &&
|
|
||||||
+ offset == linfo64.lo_offset)
|
|
||||||
+ ret = 1;
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ if (ioctl(dev, LOOP_GET_STATUS, &linfo) == 0) {
|
|
||||||
+ if (file->st_dev == linfo.lo_device &&
|
|
||||||
+ file->st_ino == linfo.lo_inode &&
|
|
||||||
+ offset == linfo.lo_offset)
|
|
||||||
+ ret = 1;
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return errno == ENXIO ? 0 : -1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* check if the loop file is already used with the same given
|
|
||||||
+ * parameters. We check for device no, inode and offset.
|
|
||||||
+ * returns: associated devname or NULL
|
|
||||||
+ */
|
|
||||||
+char *
|
|
||||||
+loopfile_used (const char *filename, unsigned long long offset) {
|
|
||||||
+ char dev[20];
|
|
||||||
+ char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
|
|
||||||
+ int i, j, fd;
|
|
||||||
+ struct stat devstat, filestat;
|
|
||||||
+ struct loop_info loopinfo;
|
|
||||||
+
|
|
||||||
+ if (stat(filename, &filestat) == -1) {
|
|
||||||
+ perror(filename);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (j = 0; j < SIZE(loop_formats); j++) {
|
|
||||||
+ for(i = 0; i < 256; i++) {
|
|
||||||
+ snprintf(dev, sizeof(dev), loop_formats[j], i);
|
|
||||||
+ if (stat (dev, &devstat) == 0 && S_ISBLK(devstat.st_mode)) {
|
|
||||||
+ fd = open (dev, O_RDONLY);
|
|
||||||
+ if (fd >= 0) {
|
|
||||||
+ int res = 0;
|
|
||||||
+
|
|
||||||
+ if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
|
|
||||||
+ res = is_associated(fd, &filestat, offset);
|
|
||||||
+ close (fd);
|
|
||||||
+ if (res == 1)
|
|
||||||
+ return xstrdup(dev);
|
|
||||||
+ }
|
|
||||||
+ continue; /* continue trying as long as devices exist */
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
+loopfile_used_with(char *devname, const char *filename, unsigned long long offset)
|
|
||||||
+{
|
|
||||||
+ struct stat statbuf;
|
|
||||||
+ int fd, ret;
|
|
||||||
+
|
|
||||||
+ if (!is_loop_device(devname))
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ if (stat(filename, &statbuf) == -1) {
|
|
||||||
+ perror(filename);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fd = open(devname, O_RDONLY);
|
|
||||||
+ if (fd == -1) {
|
|
||||||
+ perror(devname);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ ret = is_associated(fd, &statbuf, offset);
|
|
||||||
+
|
|
||||||
+ close(fd);
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int
|
|
||||||
is_loop_device (const char *device) {
|
|
||||||
struct stat statbuf;
|
|
||||||
@@ -284,6 +380,16 @@ set_loop(const char *device, const char
|
|
||||||
char *filename;
|
|
||||||
char res_file[PATH_MAX+1];
|
|
||||||
|
|
||||||
+ if (verbose) {
|
|
||||||
+ char *xdev = loopfile_used(file, offset);
|
|
||||||
+
|
|
||||||
+ if (xdev) {
|
|
||||||
+ printf(_("warning: %s is already associated with %s\n"),
|
|
||||||
+ file, xdev);
|
|
||||||
+ free(xdev);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
mode = (*loopro ? O_RDONLY : O_RDWR);
|
|
||||||
if ((ffd = open(file, mode)) < 0) {
|
|
||||||
if (!*loopro && errno == EROFS)
|
|
||||||
Index: util-linux-ng-2.13.1/mount/lomount.h
|
|
||||||
===================================================================
|
|
||||||
--- util-linux-ng-2.13.1.orig/mount/lomount.h
|
|
||||||
+++ util-linux-ng-2.13.1/mount/lomount.h
|
|
||||||
@@ -4,3 +4,6 @@ extern int set_loop(const char *, const
|
|
||||||
extern int del_loop(const char *);
|
|
||||||
extern int is_loop_device(const char *);
|
|
||||||
extern char * find_unused_loop_device(void);
|
|
||||||
+
|
|
||||||
+extern int loopfile_used_with(char *devname, const char *filename, unsigned long long offset);
|
|
||||||
+extern char *loopfile_used (const char *filename, unsigned long long offset);
|
|
||||||
Index: util-linux-ng-2.13.1/mount/mount.c
|
|
||||||
===================================================================
|
|
||||||
--- util-linux-ng-2.13.1.orig/mount/mount.c
|
|
||||||
+++ util-linux-ng-2.13.1/mount/mount.c
|
|
||||||
@@ -42,6 +42,7 @@
|
|
||||||
#include "mount_paths.h"
|
|
||||||
#include "env.h"
|
|
||||||
#include "nls.h"
|
|
||||||
+#include "realpath.h"
|
|
||||||
|
|
||||||
#define DO_PS_FIDDLING
|
|
||||||
|
|
||||||
@@ -833,9 +834,49 @@ suid_check(const char *spec, const char
|
|
||||||
*flags &= ~(MS_OWNER | MS_GROUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* Check, if there already exists a mounted loop device on the mountpoint node
|
|
||||||
+ * with the same parameters.
|
|
||||||
+ */
|
|
||||||
+static int
|
|
||||||
+is_mounted_same_loopfile(const char *node0, const char *loopfile, unsigned long long offset)
|
|
||||||
+{
|
|
||||||
+ struct mntentchn *mnt = NULL;
|
|
||||||
+ char node[PATH_MAX+1];
|
|
||||||
+ int res = 0;
|
|
||||||
+
|
|
||||||
+ myrealpath(node0, node, PATH_MAX);
|
|
||||||
+
|
|
||||||
+ /* Search for mountpoint node in mtab,
|
|
||||||
+ * procceed if any of these has the loop option set or
|
|
||||||
+ * the device is a loop device
|
|
||||||
+ */
|
|
||||||
+ mnt = getmntdirbackward(node, mnt);
|
|
||||||
+ if (!mnt) {
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+ for(; mnt && res == 0; mnt = getmntdirbackward(node, mnt)) {
|
|
||||||
+ char *p;
|
|
||||||
+
|
|
||||||
+ if (strncmp(mnt->m.mnt_fsname, "/dev/loop", 9) == 0)
|
|
||||||
+ res = loopfile_used_with((char *) mnt->m.mnt_fsname,
|
|
||||||
+ loopfile, offset);
|
|
||||||
+
|
|
||||||
+ else if ((p = strstr(mnt->m.mnt_opts, "loop="))) {
|
|
||||||
+ char *dev = xstrdup(p+5);
|
|
||||||
+ if ((p = strchr(dev, ',')))
|
|
||||||
+ *p = '\0';
|
|
||||||
+ res = loopfile_used_with(dev, loopfile, offset);
|
|
||||||
+ free(dev);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return res;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int
|
|
||||||
loop_check(const char **spec, const char **type, int *flags,
|
|
||||||
- int *loop, const char **loopdev, const char **loopfile) {
|
|
||||||
+ int *loop, const char **loopdev, const char **loopfile,
|
|
||||||
+ const char *node) {
|
|
||||||
int looptype;
|
|
||||||
unsigned long long offset;
|
|
||||||
|
|
||||||
@@ -876,6 +917,11 @@ loop_check(const char **spec, const char
|
|
||||||
|
|
||||||
offset = opt_offset ? strtoull(opt_offset, NULL, 0) : 0;
|
|
||||||
|
|
||||||
+ if (is_mounted_same_loopfile(node, *loopfile, offset)) {
|
|
||||||
+ error(_("mount: according to mtab %s is already mounted on %s as loop"), *loopfile, node);
|
|
||||||
+ return EX_FAIL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
do {
|
|
||||||
if (!*loopdev || !**loopdev)
|
|
||||||
*loopdev = find_unused_loop_device();
|
|
||||||
@@ -1061,7 +1107,7 @@ try_mount_one (const char *spec0, const
|
|
||||||
* stale assignments of files to loop devices. Nasty when used for
|
|
||||||
* encryption.
|
|
||||||
*/
|
|
||||||
- res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile);
|
|
||||||
+ res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile, node);
|
|
||||||
if (res)
|
|
||||||
goto out;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user