Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slot already mounted detection fails with symlinks #388

Open
xyzzy42 opened this issue Dec 19, 2018 · 3 comments · May be fixed by #406
Open

Slot already mounted detection fails with symlinks #388

xyzzy42 opened this issue Dec 19, 2018 · 3 comments · May be fixed by #406
Labels

Comments

@xyzzy42
Copy link

xyzzy42 commented Dec 19, 2018

I've configured a slot to have a device path which is a symlink, such as /dev/disk/by-partlabel/rootfs0. Rauc tries to determine if this slot is already mounted, but it does this by comparing the device name, like above, with a list of mounted device from g_unix_mounts_get(). But that list will use a device name like /dev/mmcblk1p2, since it's not created by the path which was mounted, but rather reconstructed from the major/minor of the device. A simple string comparison of the two paths fails, even though they are the same device.

This results in determine_slot_states() failing to detect the existing mount and set ext_mount_point. Later, load_slot_status_locally() will try to remount the already mounted filesystem and fail.

@xyzzy42
Copy link
Author

xyzzy42 commented Dec 19, 2018

A solution to this would be to normalize device paths before comparing them. This could be done by recursively following symlinks, i.e. realpath(), but that does not catch a number of cases.

The mounted device could be a file which is loopback mounted (which is already detected by rauc). This file could have multiple hard links to it. That would not be detected by comparing realpaths.

There is no rule that only one device node of a given type/major/minor combo can exist. It's perfectly possible to mknod multiple nodes for the same underlying device. This, much like multiple hardlinks to a file, it not detected by comparing realpaths.

Here's a solution which allows things that can be mounted to be compared in a way that is immune to the above and not terribly complex.

// Something that is, or can be, mounted onto a mount point
typedef struct {
        gboolean is_device; // vs being a loop mounted file
        dev_t dev;    // the device, or for a file, the device the file is on
        ino_t inode;  // inode of file for a non-device
} MountableObj;

// Take a device (or file) path and normalize it
static MountableObj *normalize_mountable_object(const gchar *devicepath)
{
        MountableObj *obj = g_new0(MountableObj, 1);
        GStatBuf st;

        if (g_stat(devicepath, &st) == -1) {
                /* Virtual filesystems like devpts trigger this case */
                g_debug("Can't stat '%s', must not be mountable", devicepath);
                return NULL;
        }

       if (S_ISBLK(st.st_mode)) {
               obj->is_device = TRUE;
               obj->dev = st.st_rdev;
       } else if (S_ISREG(st.st_mode)) {
               obj->is_device = FALSE;
               obj->dev = st.st_dev;
               obj->inode = st.st_ino;
       } else {
               g_debug("Device '%s' is not something which is mountable", devicepath);
               g_clear_pointer(&obj, g_free);
       }
       return obj;
}

/* Compare two MountableObj for equality */
static gboolean is_same_mountable_object(const MountableObj *a, const MountableObj *b)
{
       return a->is_device == b->is_device && a->dev == b->dev &&
               (a->is_device || a->inode == b->inode);
}

@ejoerns ejoerns added the bug label Dec 21, 2018
@xyzzy42
Copy link
Author

xyzzy42 commented Jan 2, 2019

I could send a pull request to fix this in the manner I described above if it appears acceptable.

@jluebbe
Copy link
Member

jluebbe commented Jan 28, 2019

@xyzzy42 Your approach seems better than what @ejoerns tried in #395. I'd suggest to pick up the virtual fs check (if it doesn't start with a slash, we don't want to try following random symlinks in the CWD):

		if (m_devpath == NULL || m_devpath[0] != '/')
				continue;

xyzzy42 pushed a commit to xyzzy42/rauc that referenced this issue Feb 8, 2019
This way a mounted slot can be found it the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
@xyzzy42 xyzzy42 linked a pull request Feb 8, 2019 that will close this issue
xyzzy42 pushed a commit to xyzzy42/rauc that referenced this issue Feb 11, 2019
This way a mounted slot can be found it the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
xyzzy42 pushed a commit to xyzzy42/rauc that referenced this issue Feb 11, 2019
This way a mounted slot can be found it the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
xyzzy42 pushed a commit to xyzzy42/rauc that referenced this issue Feb 11, 2019
This way a mounted slot can be found it the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
xyzzy42 pushed a commit to xyzzy42/rauc that referenced this issue Feb 25, 2019
This way a mounted slot can be found if the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

This is a fallback after simplying comparing the paths, as if the paths
are the same then the devices must the same too.  This avoids chaning
behavior in cases there the devices do not exist, for instance if rauc
status before a device is online.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
xyzzy42 pushed a commit to xyzzy42/rauc that referenced this issue Feb 25, 2019
This way a mounted slot can be found if the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

This is a fallback after simplying comparing the paths, as if the paths
are the same then the devices must the same too.  This avoids chaning
behavior in cases there the devices do not exist, for instance if rauc
status before a device is online.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
xyzzy42 pushed a commit to xyzzy42/rauc that referenced this issue Mar 20, 2019
This way a mounted slot can be found if the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

This is a fallback after simplying comparing the paths, as if the paths
are the same then the devices must the same too.  This avoids chaning
behavior in cases there the devices do not exist, for instance if rauc
status before a device is online.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
xyzzy42 pushed a commit to xyzzy42/rauc that referenced this issue Mar 21, 2019
This way a mounted slot can be found if the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

This is a fallback after simplying comparing the paths, as if the paths
are the same then the devices must the same too.  This avoids chaning
behavior in cases there the devices do not exist, for instance if rauc
status before a device is online.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
xyzzy42 pushed a commit to xyzzy42/rauc that referenced this issue Mar 21, 2019
This way a mounted slot can be found if the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

This is a fallback after simplying comparing the paths, as if the paths
are the same then the devices must the same too.  This avoids chaning
behavior in cases there the devices do not exist, for instance if rauc
status before a device is online.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
jluebbe pushed a commit to xyzzy42/rauc that referenced this issue Feb 10, 2020
This way a mounted slot can be found if the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

This is a fallback after simply comparing the paths, as if the paths
are the same then the devices must the same too.  This avoids changing
behavior in cases there the devices do not exist, for instance if rauc
status before a device is online.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
jluebbe pushed a commit to xyzzy42/rauc that referenced this issue Apr 21, 2020
This way a mounted slot can be found if the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

This is a fallback after simply comparing the paths, as if the paths
are the same then the devices must the same too.  This avoids changing
behavior in cases there the devices do not exist, for instance if rauc
status before a device is online.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
ejoerns pushed a commit to ejoerns/rauc that referenced this issue Aug 30, 2020
This way a mounted slot can be found if the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

This is a fallback after simply comparing the paths, as if the paths
are the same then the devices must the same too.  This avoids changing
behavior in cases there the devices do not exist, for instance if rauc
status before a device is online.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
ejoerns pushed a commit to ejoerns/rauc that referenced this issue Apr 12, 2021
This way a mounted slot can be found if the path used to mount the
device is not the same as the path in the rauc configuration file.
E.g., the configuration file uses a link like
/dev/disk/by-partlabel/rootfs0 while the kernel's list of mounted
devices uses a name like /dev/mmcblk1p2.

This is a fallback after simply comparing the paths, as if the paths
are the same then the devices must the same too.  This avoids changing
behavior in cases there the devices do not exist, for instance if rauc
status before a device is online.

Not being able to detect that the current rootfs is already mounted
causes rauc to try to mount the slot, which will fail.

Fixes rauc#388.

Signed-off-by: Trent Piepho <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants