summaryrefslogtreecommitdiffstats
path: root/libmount/src
diff options
context:
space:
mode:
Diffstat (limited to 'libmount/src')
-rw-r--r--libmount/src/context.c47
-rw-r--r--libmount/src/context_mount.c27
-rw-r--r--libmount/src/libmount.h.in5
-rw-r--r--libmount/src/libmount.sym6
-rw-r--r--libmount/src/mountP.h2
5 files changed, 86 insertions, 1 deletions
diff --git a/libmount/src/context.c b/libmount/src/context.c
index e731749b4..6a7c7d351 100644
--- a/libmount/src/context.c
+++ b/libmount/src/context.c
@@ -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;
@@ -478,6 +479,48 @@ int mnt_context_is_rdonly_umount(struct libmnt_context *cxt)
}
/**
+ * 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
* @disable: TRUE or FALSE
@@ -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!"));
diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c
index 6368e9ba8..1c8a62924 100644
--- a/libmount/src/context_mount.c
+++ b/libmount/src/context_mount.c
@@ -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;
}
diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in
index f191a52fe..3f2da3230 100644
--- a/libmount/src/libmount.h.in
+++ b/libmount/src/libmount.h.in
@@ -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));
diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym
index f0210c240..354332b43 100644
--- a/libmount/src/libmount.sym
+++ b/libmount/src/libmount.sym
@@ -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;
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
index 2baab55de..42957ecb9 100644
--- a/libmount/src/mountP.h
+++ b/libmount/src/mountP.h
@@ -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