libmount: support MS_RDONLY on write-protected devices
This feature is supported by mount(8) only. It seems better move this code to libmount. The results is more simple mount(8) and the feature is accessible for all libmount users. Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
863cf02a14
commit
6dede2f2f7
|
@ -35,8 +35,10 @@ mnt_context_enable_fork
|
|||
mnt_context_enable_lazy
|
||||
mnt_context_enable_loopdel
|
||||
mnt_context_enable_rdonly_umount
|
||||
mnt_context_enable_rwonly_mount;
|
||||
mnt_context_enable_sloppy
|
||||
mnt_context_enable_verbose
|
||||
mnt_context_forced_rdonly;
|
||||
mnt_context_get_cache
|
||||
mnt_context_get_fs
|
||||
mnt_context_get_fstab
|
||||
|
@ -72,6 +74,7 @@ mnt_context_is_nomtab
|
|||
mnt_context_is_parent
|
||||
mnt_context_is_rdonly_umount
|
||||
mnt_context_is_restricted
|
||||
mnt_context_is_rwonly_mount;
|
||||
mnt_context_is_sloppy
|
||||
mnt_context_is_swapmatch
|
||||
mnt_context_is_verbose
|
||||
|
|
|
@ -172,6 +172,7 @@ int mnt_reset_context(struct libmnt_context *cxt)
|
|||
cxt->flags |= (fl & MNT_FL_FORCE);
|
||||
cxt->flags |= (fl & MNT_FL_NOCANONICALIZE);
|
||||
cxt->flags |= (fl & MNT_FL_RDONLY_UMOUNT);
|
||||
cxt->flags |= (fl & MNT_FL_RWONLY_MOUNT);
|
||||
cxt->flags |= (fl & MNT_FL_NOSWAPMATCH);
|
||||
cxt->flags |= (fl & MNT_FL_TABPATHS_CHECKED);
|
||||
return 0;
|
||||
|
@ -477,6 +478,48 @@ int mnt_context_is_rdonly_umount(struct libmnt_context *cxt)
|
|||
return cxt->flags & MNT_FL_RDONLY_UMOUNT ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnt_context_enable_rwonly_mount:
|
||||
* @cxt: mount context
|
||||
* @enable: TRUE or FALSE
|
||||
*
|
||||
* Force read-write mount; if enabled libmount will never try MS_RDONLY
|
||||
* after failed mount(2) EROFS. (See mount(8) man page, option -w).
|
||||
*
|
||||
* Returns: 0 on success, negative number in case of error.
|
||||
*/
|
||||
int mnt_context_enable_rwonly_mount(struct libmnt_context *cxt, int enable)
|
||||
{
|
||||
return set_flag(cxt, MNT_FL_RWONLY_MOUNT, enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnt_context_is_rwonly_mount
|
||||
* @cxt: mount context
|
||||
*
|
||||
* See also mnt_context_enable_rwonly_mount() and mount(8) man page,
|
||||
* option -w.
|
||||
*
|
||||
* Returns: 1 if only read-write mount is allowed.
|
||||
*/
|
||||
int mnt_context_is_rwonly_mount(struct libmnt_context *cxt)
|
||||
{
|
||||
return cxt->flags & MNT_FL_RWONLY_MOUNT ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnt_context_forced_rdonly:
|
||||
* @cxt: mount context
|
||||
*
|
||||
* See also mnt_context_enable_rwonly_mount().
|
||||
*
|
||||
* Returns: 1 if mounted read-only on write-protected device.
|
||||
*/
|
||||
int mnt_context_forced_rdonly(struct libmnt_context *cxt)
|
||||
{
|
||||
return cxt->flags & MNT_FL_FORCED_RDONLY ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnt_context_disable_helpers:
|
||||
* @cxt: mount context
|
||||
|
@ -2002,8 +2045,10 @@ int mnt_context_apply_fstab(struct libmnt_context *cxt)
|
|||
if (!cxt || !cxt->fs)
|
||||
return -EINVAL;
|
||||
|
||||
if (mnt_context_tab_applied(cxt)) /* already applied */
|
||||
if (mnt_context_tab_applied(cxt)) { /* already applied */
|
||||
DBG(CXT, ul_debugobj(cxt, "fstab already applied -- skip"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mnt_context_is_restricted(cxt)) {
|
||||
DBG(CXT, ul_debugobj(cxt, "force fstab usage for non-root users!"));
|
||||
|
|
|
@ -1083,6 +1083,7 @@ int mnt_context_mount(struct libmnt_context *cxt)
|
|||
assert(cxt->helper_exec_status == 1);
|
||||
assert(cxt->syscall_status == 1);
|
||||
|
||||
again:
|
||||
rc = mnt_context_prepare_mount(cxt);
|
||||
if (!rc)
|
||||
rc = mnt_context_prepare_update(cxt);
|
||||
|
@ -1090,6 +1091,32 @@ int mnt_context_mount(struct libmnt_context *cxt)
|
|||
rc = mnt_context_do_mount(cxt);
|
||||
if (!rc)
|
||||
rc = mnt_context_update_tabs(cxt);
|
||||
|
||||
/*
|
||||
* Read-only device; try mount filesystem read-only
|
||||
*/
|
||||
if ((rc == -EROFS && !mnt_context_syscall_called(cxt)) /* before syscall; rdonly loopdev */
|
||||
|| mnt_context_get_syscall_errno(cxt) == EROFS /* syscall failed with EROFS */
|
||||
|| mnt_context_get_syscall_errno(cxt) == EACCES) /* syscall failed with EACCES */
|
||||
{
|
||||
unsigned long mflags = 0;
|
||||
|
||||
mnt_context_get_mflags(cxt, &mflags);
|
||||
|
||||
if (!(mflags & MS_RDONLY) /* not yet RDONLY */
|
||||
&& !(mflags & MS_REMOUNT) /* not remount */
|
||||
&& !(mflags & MS_BIND) /* not bin mount */
|
||||
&& !mnt_context_is_rwonly_mount(cxt)) { /* no explicit read-write */
|
||||
|
||||
assert(!(cxt->flags & MNT_FL_FORCED_RDONLY));
|
||||
DBG(CXT, ul_debugobj(cxt, "write-protected source, trying RDONLY."));
|
||||
|
||||
mnt_context_reset_status(cxt);
|
||||
mnt_context_set_mflags(cxt, mflags | MS_RDONLY);
|
||||
cxt->flags |= MNT_FL_FORCED_RDONLY;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -610,6 +610,7 @@ extern int mnt_context_set_optsmode(struct libmnt_context *cxt, int mode);
|
|||
extern int mnt_context_disable_canonicalize(struct libmnt_context *cxt, int disable);
|
||||
extern int mnt_context_enable_lazy(struct libmnt_context *cxt, int enable);
|
||||
extern int mnt_context_enable_rdonly_umount(struct libmnt_context *cxt, int enable);
|
||||
extern int mnt_context_enable_rwonly_mount(struct libmnt_context *cxt, int enable);
|
||||
extern int mnt_context_disable_helpers(struct libmnt_context *cxt, int disable);
|
||||
extern int mnt_context_enable_sloppy(struct libmnt_context *cxt, int enable);
|
||||
extern int mnt_context_enable_fake(struct libmnt_context *cxt, int enable);
|
||||
|
@ -626,6 +627,8 @@ extern int mnt_context_is_lazy(struct libmnt_context *cxt)
|
|||
__ul_attribute__((nonnull));
|
||||
extern int mnt_context_is_rdonly_umount(struct libmnt_context *cxt)
|
||||
__ul_attribute__((nonnull));
|
||||
extern int mnt_context_is_rwonly_mount(struct libmnt_context *cxt)
|
||||
__ul_attribute__((nonnull));
|
||||
extern int mnt_context_is_sloppy(struct libmnt_context *cxt)
|
||||
__ul_attribute__((nonnull));
|
||||
extern int mnt_context_is_fake(struct libmnt_context *cxt)
|
||||
|
@ -644,6 +647,8 @@ extern int mnt_context_is_nocanonicalize(struct libmnt_context *cxt)
|
|||
__ul_attribute__((nonnull));
|
||||
extern int mnt_context_is_swapmatch(struct libmnt_context *cxt)
|
||||
__ul_attribute__((nonnull));
|
||||
extern int mnt_context_forced_rdonly(struct libmnt_context *cxt)
|
||||
__ul_attribute__((nonnull));
|
||||
|
||||
extern int mnt_context_is_fork(struct libmnt_context *cxt)
|
||||
__ul_attribute__((nonnull));
|
||||
|
|
|
@ -315,3 +315,9 @@ MOUNT_2.28 {
|
|||
mnt_table_find_target_with_option;
|
||||
mnt_fs_set_priority;
|
||||
} MOUNT_2.26;
|
||||
|
||||
MOUNT_2.30 {
|
||||
mnt_context_is_rwonly_mount;
|
||||
mnt_context_forced_rdonly;
|
||||
mnt_context_enable_rwonly_mount;
|
||||
} MOUNT_2.28;
|
||||
|
|
|
@ -328,6 +328,7 @@ struct libmnt_context
|
|||
#define MNT_FL_RDONLY_UMOUNT (1 << 11) /* remount,ro after EBUSY umount(2) */
|
||||
#define MNT_FL_FORK (1 << 12)
|
||||
#define MNT_FL_NOSWAPMATCH (1 << 13)
|
||||
#define MNT_FL_RWONLY_MOUNT (1 << 14) /* explicit mount -w; never try read-only */
|
||||
|
||||
#define MNT_FL_MOUNTDATA (1 << 20)
|
||||
#define MNT_FL_TAB_APPLIED (1 << 21) /* mtab/fstab merged to cxt->fs */
|
||||
|
@ -338,6 +339,7 @@ struct libmnt_context
|
|||
#define MNT_FL_LOOPDEV_READY (1 << 26) /* /dev/loop<N> initialized by the library */
|
||||
#define MNT_FL_MOUNTOPTS_FIXED (1 << 27)
|
||||
#define MNT_FL_TABPATHS_CHECKED (1 << 28)
|
||||
#define MNT_FL_FORCED_RDONLY (1 << 29) /* mounted read-only on write-protected device */
|
||||
|
||||
/* default flags */
|
||||
#define MNT_FL_DEFAULT 0
|
||||
|
|
|
@ -807,8 +807,12 @@ Mount the partition that has the specified
|
|||
Verbose mode.
|
||||
.TP
|
||||
.BR \-w , " \-\-rw" , " \-\-read\-write"
|
||||
Mount the filesystem read/write. This is the default. A synonym is
|
||||
Mount the filesystem read/write. The read-write is kernel default. A synonym is
|
||||
.BR "\-o rw" .
|
||||
|
||||
Note that specify \fB\-w\fR on command line forces \fBmount\fR command
|
||||
to never try read-only mount on write-protected devices. The default is
|
||||
try read-only if the previous mount syscall with read-write flags failed.
|
||||
.TP
|
||||
.BR \-V , " \-\-version"
|
||||
Display version information and exit.
|
||||
|
|
|
@ -51,8 +51,6 @@
|
|||
* --options-source-force MNT_OMODE_FORCE
|
||||
*/
|
||||
|
||||
static int readwrite;
|
||||
|
||||
static int mk_exit_code(struct libmnt_context *cxt, int rc);
|
||||
|
||||
static void __attribute__((__noreturn__)) exit_non_root(const char *option)
|
||||
|
@ -369,7 +367,6 @@ static int mk_exit_code(struct libmnt_context *cxt, int rc)
|
|||
const char *tgt = mnt_context_get_target(cxt);
|
||||
const char *src = mnt_context_get_source(cxt);
|
||||
|
||||
try_readonly:
|
||||
if (mnt_context_helper_executed(cxt)) {
|
||||
/*
|
||||
* /sbin/mount.<type> called, return status
|
||||
|
@ -385,6 +382,9 @@ try_readonly:
|
|||
*/
|
||||
selinux_warning(cxt, tgt);
|
||||
|
||||
if (mnt_context_forced_rdonly(cxt))
|
||||
warnx(_("WARNING: device write-protected, mounted read-only"));
|
||||
|
||||
return MOUNT_EX_SUCCESS; /* mount(2) success */
|
||||
}
|
||||
|
||||
|
@ -404,13 +404,14 @@ try_readonly:
|
|||
return MOUNT_EX_USAGE;
|
||||
/* -EROFS before syscall can happen only for loop mount */
|
||||
case -EROFS:
|
||||
warnx(_("%s is used as read only loop, mounting read-only"), src);
|
||||
mnt_context_reset_status(cxt);
|
||||
mnt_context_set_mflags(cxt, mflags | MS_RDONLY);
|
||||
rc = mnt_context_mount(cxt);
|
||||
if (!rc)
|
||||
rc = mnt_context_finalize_mount(cxt);
|
||||
goto try_readonly;
|
||||
if (mflags & MS_RDONLY)
|
||||
warnx(_("cannot mount %s read-only"), src);
|
||||
else if (mnt_context_is_rwonly_mount(cxt))
|
||||
warnx(_("%s is write-protected but explicit `-w' flag given"), src);
|
||||
else if (mflags & MS_REMOUNT)
|
||||
warnx(_("cannot remount %s read-write, is write-protected"), src);
|
||||
warnx(_("mount %s on %s failed"), src, tgt);
|
||||
return MOUNT_EX_USAGE;
|
||||
case -MNT_ERR_NOFSTAB:
|
||||
if (mnt_context_is_swapmatch(cxt)) {
|
||||
warnx(_("can't find %s in %s"),
|
||||
|
@ -481,7 +482,6 @@ try_readonly:
|
|||
*/
|
||||
syserr = mnt_context_get_syscall_errno(cxt);
|
||||
|
||||
|
||||
switch(syserr) {
|
||||
case EPERM:
|
||||
if (geteuid() == 0) {
|
||||
|
@ -620,27 +620,11 @@ try_readonly:
|
|||
case EROFS:
|
||||
if (mflags & MS_RDONLY)
|
||||
warnx(_("cannot mount %s read-only"), src);
|
||||
|
||||
else if (readwrite)
|
||||
else if (mnt_context_is_rwonly_mount(cxt))
|
||||
warnx(_("%s is write-protected but explicit `-w' flag given"), src);
|
||||
|
||||
else if (mflags & MS_REMOUNT)
|
||||
warnx(_("cannot remount %s read-write, is write-protected"), src);
|
||||
|
||||
else if (mflags & MS_BIND)
|
||||
warn(_("mount %s on %s failed"), src, tgt);
|
||||
|
||||
else {
|
||||
warnx(_("%s is write-protected, mounting read-only"), src);
|
||||
|
||||
mnt_context_reset_status(cxt);
|
||||
mnt_context_set_mflags(cxt, mflags | MS_RDONLY);
|
||||
rc = mnt_context_do_mount(cxt);
|
||||
if (!rc)
|
||||
rc = mnt_context_finalize_mount(cxt);
|
||||
|
||||
goto try_readonly;
|
||||
}
|
||||
warnx(_("mount %s on %s failed"), src, tgt);
|
||||
break;
|
||||
|
||||
case ENOMEDIUM:
|
||||
|
@ -924,7 +908,7 @@ int main(int argc, char **argv)
|
|||
break;
|
||||
case 'r':
|
||||
append_option(cxt, "ro");
|
||||
readwrite = 0;
|
||||
mnt_context_enable_rwonly_mount(cxt, FALSE);
|
||||
break;
|
||||
case 'v':
|
||||
mnt_context_enable_verbose(cxt, TRUE);
|
||||
|
@ -934,7 +918,7 @@ int main(int argc, char **argv)
|
|||
break;
|
||||
case 'w':
|
||||
append_option(cxt, "rw");
|
||||
readwrite = 1;
|
||||
mnt_context_enable_rwonly_mount(cxt, TRUE);
|
||||
break;
|
||||
case 'o':
|
||||
append_option(cxt, optarg);
|
||||
|
|
Loading…
Reference in New Issue