mount: check for unsuccessful read-only bind mounts

Linux kernel allows to use MS_RDONLY together with MS_BIND,
unfortunately the MS_RDONLY is silently ignored and the target
mountpoint is still read-write. Then we have 'ro' in mtab and 'rw' in
/proc/mounts.

This patch checks for this situation by access(2) or futimens(2)
(change atime) and mtab is properly updated and user informed.

Reported-by: Terry Burton <tez@terryburton.co.uk>
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2009-11-19 15:56:12 +01:00
parent 75c1d2aee6
commit b7ce600d3d
2 changed files with 47 additions and 0 deletions

View File

@ -145,6 +145,7 @@ AC_CHECK_DECLS([_NL_TIME_WEEK_1STDAY],[],[],[[#include <langinfo.h>]])
AC_CHECK_FUNCS(
[inet_aton \
futimens \
fsync \
getdomainname \
get_current_dir_name \

View File

@ -1225,6 +1225,41 @@ cdrom_setspeed(const char *spec) {
}
}
/*
* Check if @node is read-only filesystem by access() or futimens().
*
* Note that access(2) uses real-UID (= useless for suid programs)
* and euidaccess(2) does not check for read-only FS.
*/
static int
is_readonly(const char *node)
{
int res = 0;
if (getuid() == geteuid()) {
if (access(node, W_OK) == -1 && errno == EROFS)
res = 1;
}
#ifdef HAVE_FUTIMENS
else {
struct timespec times[2];
int fd = open(node, O_RDONLY);
if (fd < 0)
goto done;
times[0].tv_nsec = UTIME_NOW; /* atime */
times[1].tv_nsec = UTIME_OMIT; /* mtime */
if (futimens(fd, times) == -1 && errno == EROFS)
res = 1;
close(fd);
}
done:
#endif
return res;
}
/*
* try_mount_one()
* Try to mount one file system.
@ -1326,6 +1361,17 @@ mount_retry:
}
}
/* Kernel allows to use MS_RDONLY for bind mounts, but the read-only request
* could be silently ignored. Check it to avoid 'ro' in ntab and 'rw' in
* /proc/mounts.
*/
if (!fake && mnt5_res == 0 &&
(flags & MS_BIND) && (flags & MS_RDONLY) && !is_readonly(node)) {
printf(_("mount: warning: %s seems to be mounted read-write.\n"), node);
flags &= ~MS_RDONLY;
}
if (fake || mnt5_res == 0) {
/* Mount succeeded, report this (if verbose) and write mtab entry. */