From 8c863d0eacf41958e39845667b3b5f9a541f1ca2 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 22 Aug 2019 13:05:06 +0200 Subject: [PATCH] eject: use O_EXCL on default * by default we assume all is umounted; so O_EXCL is no problem, otherwise there is bug or race (someone else remounted the device)... * --force and --no-umount disable O_EXCL Addresses: https://github.com/karelzak/util-linux/issues/423 Signed-off-by: Karel Zak --- sys-utils/eject.1 | 17 +++++++++++++---- sys-utils/eject.c | 20 +++++++++++++++++--- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/sys-utils/eject.1 b/sys-utils/eject.1 index f901b239d6..0958e052e2 100644 --- a/sys-utils/eject.1 +++ b/sys-utils/eject.1 @@ -27,8 +27,12 @@ There are four different methods of ejecting, depending on whether the device is a CD-ROM, SCSI device, removable floppy, or tape. By default \fBeject\fR tries all four methods in order until it succeeds. .PP -If a device partition is specified, the whole-disk device is used. If the device -or a device partition is currently mounted, it is unmounted before ejecting. +If a device partition is specified, the whole-disk device is used. +.PP +If the device or a device partition is currently mounted, it is unmounted +before ejecting. The eject is processed on exclusive open block device +file descriptor if \fB\-\-no\-unmount\fP or \fB\-\-force\fP are not specified. + .SH OPTIONS .TP .BR \-a , " \-\-auto on" | off @@ -45,7 +49,8 @@ is referred to as 0, not 1. List the default device name. .TP .BR \-F , " \-\-force" -Force eject, don't check device type. +Force eject, don't check device type, don't open device with exclusive lock. +The successful result may be false positive on non hot-pluggable devices. .TP .BR \-f , " \-\-floppy" This option specifies that the drive should be ejected using a removable floppy @@ -67,7 +72,11 @@ to eject the media. It will attempt to unmount only the device or mountpoint given on the command line. .TP .BR \-m , " \-\-no\-unmount" -The option tells eject to not try to unmount at all. +The option tells eject to not try to unmount at all. If this option is not +specified than +.B eject +opens the device with O_EXCL flag to be sure that the device is not used (since +v2.35). .TP .BR \-n , " \-\-noop" With this option the selected device is displayed but no action is performed. diff --git a/sys-utils/eject.c b/sys-utils/eject.c index d2e76d2ffe..2f3b200bf8 100644 --- a/sys-utils/eject.c +++ b/sys-utils/eject.c @@ -96,6 +96,9 @@ struct eject_control { x_option:1, a_arg:1, i_arg:1; + + unsigned int force_exclusive; /* use O_EXCL */ + long int c_arg; /* changer slot number */ long int x_arg; /* cd speed */ }; @@ -686,9 +689,12 @@ static void umount_one(const struct eject_control *ctl, const char *name) /* Open a device file. */ static void open_device(struct eject_control *ctl) { - ctl->fd = open(ctl->device, O_RDWR | O_NONBLOCK); + int extra = ctl->F_option == 0 && /* never use O_EXCL on --force */ + ctl->force_exclusive ? O_EXCL : 0; + + ctl->fd = open(ctl->device, O_RDWR | O_NONBLOCK | extra); if (ctl->fd < 0) - ctl->fd = open(ctl->device, O_RDONLY | O_NONBLOCK); + ctl->fd = open(ctl->device, O_RDONLY | O_NONBLOCK | extra); if (ctl->fd == -1) err(EXIT_FAILURE, _("cannot open %s"), ctl->device); } @@ -755,6 +761,9 @@ static char *get_disk_devname(const char *device) return st.st_rdev == diskno ? NULL : find_device(diskname); } +/* umount all partitions if -M not specified, otherwise returns + * number of the mounted partitions only. + */ static int umount_partitions(struct eject_control *ctl) { struct path_cxt *pc = NULL; @@ -970,7 +979,7 @@ int main(int argc, char **argv) * partition is mounted. */ if (!ctl.m_option) { - int ct = umount_partitions(&ctl); + int ct = umount_partitions(&ctl); /* umount all, or count mounted on -M */ if (ct == 0 && mountpoint) umount_one(&ctl, mountpoint); /* probably whole-device */ @@ -981,6 +990,11 @@ int main(int argc, char **argv) else if (ct) errx(EXIT_FAILURE, _("error: %s: device in use"), ctl.device); } + /* Now, we assume the device is no more used, use O_EXCL to be + * resistant against our bugs and possible races (someone else + * remounted the device). + */ + ctl.force_exclusive = 1; } /* handle -c option */ -- 2.47.2