libmount: add post-mount checks to detect ro/rw

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2012-01-16 12:09:36 +01:00
parent 8b470b20d7
commit f9906424d4
4 changed files with 72 additions and 8 deletions

View File

@ -289,8 +289,7 @@ int mnt_context_setup_loopdev(struct libmnt_context *cxt)
* mount planned read-write, but loopdev is read-only,
* let's fix mount options...
*/
cxt->mountflags |= MS_RDONLY;
mnt_context_set_mflags(cxt, cxt->mountflags | MS_RDONLY);
/* we have to keep the device open until mount(1),
* otherwise it will auto-cleared by kernel

View File

@ -455,10 +455,6 @@ static int do_mount(struct libmnt_context *cxt, const char *try_type)
rc = mnt_fs_set_fstype(fs, try_type);
}
/* TODO: check if the result is really read-only/read-write
* and if necessary update cxt->mountflags
*/
return rc;
}
@ -591,6 +587,7 @@ int mnt_context_prepare_mount(struct libmnt_context *cxt)
int mnt_context_do_mount(struct libmnt_context *cxt)
{
const char *type;
int res;
assert(cxt);
assert(cxt->fs);
@ -607,9 +604,40 @@ int mnt_context_do_mount(struct libmnt_context *cxt)
type = mnt_fs_get_fstype(cxt->fs);
if (type)
return do_mount(cxt, NULL);
res = do_mount(cxt, NULL);
else
res = do_mount_by_pattern(cxt, cxt->fstype_pattern);
return do_mount_by_pattern(cxt, cxt->fstype_pattern);
if (mnt_context_get_status(cxt)
&& !(cxt->flags & MNT_FL_FAKE)
&& !cxt->helper) {
/*
* Mounted by mount(2), do some post-mount checks
*
* Kernel allows to use MS_RDONLY for bind mounts, but the
* read-only request could be silently ignored. Check it to
* avoid 'ro' in mtab and 'rw' in /proc/mounts.
*/
if ((cxt->mountflags & MS_BIND)
&& (cxt->mountflags & MS_RDONLY)
&& !mnt_is_readonly(mnt_context_get_target(cxt)))
mnt_context_set_mflags(cxt,
cxt->mountflags & ~MS_RDONLY);
/* Kernel can silently add MS_RDONLY flag when mounting file
* system that does not have write support. Check this to avoid
* 'ro' in /proc/mounts and 'rw' in mtab.
*/
if (!(cxt->mountflags & (MS_RDONLY | MS_PROPAGATION | MS_MOVE))
&& mnt_is_readonly(mnt_context_get_target(cxt)))
mnt_context_set_mflags(cxt,
cxt->mountflags | MS_RDONLY);
}
return res;
}
/**

View File

@ -129,6 +129,8 @@ extern int mnt_run_test(struct libmnt_test *tests, int argc, char *argv[]);
extern int endswith(const char *s, const char *sx);
extern int startswith(const char *s, const char *sx);
extern int mnt_is_readonly(const char *path);
extern int mnt_parse_offset(const char *str, size_t len, uintmax_t *res);
extern int mnt_chdir_to_parent(const char *target, char **filename);

View File

@ -145,6 +145,41 @@ err:
return rc;
}
/*
* Check if @path is on read-only filesystem independently on file permissions.
*/
int mnt_is_readonly(const char *path)
{
if (access(path, W_OK) == 0)
return 0;
if (errno == EROFS)
return 1;
if (errno != EACCES)
return 0;
#ifdef HAVE_FUTIMENS
/*
* access(2) returns EACCES on read-only FS:
*
* - for set-uid application if one component of the path is not
* accessible for the current rUID. (Note that euidaccess(2) does not
* check for EROFS at all).
*
* - for read-write filesystem with read-only VFS node (aka -o remount,ro,bind)
*/
{
struct timespec times[2];
times[0].tv_nsec = UTIME_NOW; /* atime */
times[1].tv_nsec = UTIME_OMIT; /* mtime */
if (utimensat(AT_FDCWD, path, times, 0) == -1)
return errno == EROFS;
}
#endif
return 0;
}
/**
* mnt_mangle:
* @str: string