forked from luck/tmp_suning_uos_patched
ovl: Provide a mount option metacopy=on/off for metadata copyup
By default metadata only copy up is disabled. Provide a mount option so that users can choose one way or other. Also provide a kernel config and module option to enable/disable metacopy feature. metacopy feature requires redirect_dir=on when upper is present. Otherwise, it requires redirect_dir=follow atleast. As of now, metacopy does not work with nfs_export=on. So if both metacopy=on and nfs_export=on then nfs_export is disabled. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
d6eac03913
commit
d5791044d2
|
@ -262,6 +262,30 @@ rightmost one and going left. In the above example lower1 will be the
|
||||||
top, lower2 the middle and lower3 the bottom layer.
|
top, lower2 the middle and lower3 the bottom layer.
|
||||||
|
|
||||||
|
|
||||||
|
Metadata only copy up
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
When metadata only copy up feature is enabled, overlayfs will only copy
|
||||||
|
up metadata (as opposed to whole file), when a metadata specific operation
|
||||||
|
like chown/chmod is performed. Full file will be copied up later when
|
||||||
|
file is opened for WRITE operation.
|
||||||
|
|
||||||
|
In other words, this is delayed data copy up operation and data is copied
|
||||||
|
up when there is a need to actually modify data.
|
||||||
|
|
||||||
|
There are multiple ways to enable/disable this feature. A config option
|
||||||
|
CONFIG_OVERLAY_FS_METACOPY can be set/unset to enable/disable this feature
|
||||||
|
by default. Or one can enable/disable it at module load time with module
|
||||||
|
parameter metacopy=on/off. Lastly, there is also a per mount option
|
||||||
|
metacopy=on/off to enable/disable this feature per mount.
|
||||||
|
|
||||||
|
Do not use metacopy=on with untrusted upper/lower directories. Otherwise
|
||||||
|
it is possible that an attacker can create a handcrafted file with
|
||||||
|
appropriate REDIRECT and METACOPY xattrs, and gain access to file on lower
|
||||||
|
pointed by REDIRECT. This should not be possible on local system as setting
|
||||||
|
"trusted." xattrs will require CAP_SYS_ADMIN. But it should be possible
|
||||||
|
for untrusted layers like from a pen drive.
|
||||||
|
|
||||||
Sharing and copying layers
|
Sharing and copying layers
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
@ -280,7 +304,7 @@ though it will not result in a crash or deadlock.
|
||||||
Mounting an overlay using an upper layer path, where the upper layer path
|
Mounting an overlay using an upper layer path, where the upper layer path
|
||||||
was previously used by another mounted overlay in combination with a
|
was previously used by another mounted overlay in combination with a
|
||||||
different lower layer path, is allowed, unless the "inodes index" feature
|
different lower layer path, is allowed, unless the "inodes index" feature
|
||||||
is enabled.
|
or "metadata only copy up" feature is enabled.
|
||||||
|
|
||||||
With the "inodes index" feature, on the first time mount, an NFS file
|
With the "inodes index" feature, on the first time mount, an NFS file
|
||||||
handle of the lower layer root directory, along with the UUID of the lower
|
handle of the lower layer root directory, along with the UUID of the lower
|
||||||
|
@ -293,6 +317,10 @@ lower root origin, mount will fail with ESTALE. An overlayfs mount with
|
||||||
does not support NFS export, lower filesystem does not have a valid UUID or
|
does not support NFS export, lower filesystem does not have a valid UUID or
|
||||||
if the upper filesystem does not support extended attributes.
|
if the upper filesystem does not support extended attributes.
|
||||||
|
|
||||||
|
For "metadata only copy up" feature there is no verification mechanism at
|
||||||
|
mount time. So if same upper is mounted with different set of lower, mount
|
||||||
|
probably will succeed but expect the unexpected later on. So don't do it.
|
||||||
|
|
||||||
It is quite a common practice to copy overlay layers to a different
|
It is quite a common practice to copy overlay layers to a different
|
||||||
directory tree on the same or different underlying filesystem, and even
|
directory tree on the same or different underlying filesystem, and even
|
||||||
to a different machine. With the "inodes index" feature, trying to mount
|
to a different machine. With the "inodes index" feature, trying to mount
|
||||||
|
|
|
@ -64,6 +64,7 @@ config OVERLAY_FS_NFS_EXPORT
|
||||||
bool "Overlayfs: turn on NFS export feature by default"
|
bool "Overlayfs: turn on NFS export feature by default"
|
||||||
depends on OVERLAY_FS
|
depends on OVERLAY_FS
|
||||||
depends on OVERLAY_FS_INDEX
|
depends on OVERLAY_FS_INDEX
|
||||||
|
depends on !OVERLAY_FS_METACOPY
|
||||||
help
|
help
|
||||||
If this config option is enabled then overlay filesystems will use
|
If this config option is enabled then overlay filesystems will use
|
||||||
the index directory to decode overlay NFS file handles by default.
|
the index directory to decode overlay NFS file handles by default.
|
||||||
|
@ -103,3 +104,21 @@ config OVERLAY_FS_XINO_AUTO
|
||||||
For more information, see Documentation/filesystems/overlayfs.txt
|
For more information, see Documentation/filesystems/overlayfs.txt
|
||||||
|
|
||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
|
config OVERLAY_FS_METACOPY
|
||||||
|
bool "Overlayfs: turn on metadata only copy up feature by default"
|
||||||
|
depends on OVERLAY_FS
|
||||||
|
select OVERLAY_FS_REDIRECT_DIR
|
||||||
|
help
|
||||||
|
If this config option is enabled then overlay filesystems will
|
||||||
|
copy up only metadata where appropriate and data copy up will
|
||||||
|
happen when a file is opened for WRITE operation. It is still
|
||||||
|
possible to turn off this feature globally with the "metacopy=off"
|
||||||
|
module option or on a filesystem instance basis with the
|
||||||
|
"metacopy=off" mount option.
|
||||||
|
|
||||||
|
Note, that this feature is not backward compatible. That is,
|
||||||
|
mounting an overlay which has metacopy only inodes on a kernel
|
||||||
|
that doesn't support this feature will have unexpected results.
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
|
@ -19,6 +19,7 @@ struct ovl_config {
|
||||||
bool index;
|
bool index;
|
||||||
bool nfs_export;
|
bool nfs_export;
|
||||||
int xino;
|
int xino;
|
||||||
|
bool metacopy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ovl_sb {
|
struct ovl_sb {
|
||||||
|
|
|
@ -64,6 +64,11 @@ static void ovl_entry_stack_free(struct ovl_entry *oe)
|
||||||
dput(oe->lowerstack[i].dentry);
|
dput(oe->lowerstack[i].dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ovl_metacopy_def = IS_ENABLED(CONFIG_OVERLAY_FS_METACOPY);
|
||||||
|
module_param_named(metacopy, ovl_metacopy_def, bool, 0644);
|
||||||
|
MODULE_PARM_DESC(ovl_metacopy_def,
|
||||||
|
"Default to on or off for the metadata only copy up feature");
|
||||||
|
|
||||||
static void ovl_dentry_release(struct dentry *dentry)
|
static void ovl_dentry_release(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct ovl_entry *oe = dentry->d_fsdata;
|
struct ovl_entry *oe = dentry->d_fsdata;
|
||||||
|
@ -347,6 +352,9 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
|
||||||
"on" : "off");
|
"on" : "off");
|
||||||
if (ofs->config.xino != ovl_xino_def())
|
if (ofs->config.xino != ovl_xino_def())
|
||||||
seq_printf(m, ",xino=%s", ovl_xino_str[ofs->config.xino]);
|
seq_printf(m, ",xino=%s", ovl_xino_str[ofs->config.xino]);
|
||||||
|
if (ofs->config.metacopy != ovl_metacopy_def)
|
||||||
|
seq_printf(m, ",metacopy=%s",
|
||||||
|
ofs->config.metacopy ? "on" : "off");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,6 +392,8 @@ enum {
|
||||||
OPT_XINO_ON,
|
OPT_XINO_ON,
|
||||||
OPT_XINO_OFF,
|
OPT_XINO_OFF,
|
||||||
OPT_XINO_AUTO,
|
OPT_XINO_AUTO,
|
||||||
|
OPT_METACOPY_ON,
|
||||||
|
OPT_METACOPY_OFF,
|
||||||
OPT_ERR,
|
OPT_ERR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -400,6 +410,8 @@ static const match_table_t ovl_tokens = {
|
||||||
{OPT_XINO_ON, "xino=on"},
|
{OPT_XINO_ON, "xino=on"},
|
||||||
{OPT_XINO_OFF, "xino=off"},
|
{OPT_XINO_OFF, "xino=off"},
|
||||||
{OPT_XINO_AUTO, "xino=auto"},
|
{OPT_XINO_AUTO, "xino=auto"},
|
||||||
|
{OPT_METACOPY_ON, "metacopy=on"},
|
||||||
|
{OPT_METACOPY_OFF, "metacopy=off"},
|
||||||
{OPT_ERR, NULL}
|
{OPT_ERR, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -452,6 +464,7 @@ static int ovl_parse_redirect_mode(struct ovl_config *config, const char *mode)
|
||||||
static int ovl_parse_opt(char *opt, struct ovl_config *config)
|
static int ovl_parse_opt(char *opt, struct ovl_config *config)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
int err;
|
||||||
|
|
||||||
config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL);
|
config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL);
|
||||||
if (!config->redirect_mode)
|
if (!config->redirect_mode)
|
||||||
|
@ -526,6 +539,14 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
|
||||||
config->xino = OVL_XINO_AUTO;
|
config->xino = OVL_XINO_AUTO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OPT_METACOPY_ON:
|
||||||
|
config->metacopy = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPT_METACOPY_OFF:
|
||||||
|
config->metacopy = false;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p);
|
pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -540,7 +561,20 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
|
||||||
config->workdir = NULL;
|
config->workdir = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ovl_parse_redirect_mode(config, config->redirect_mode);
|
err = ovl_parse_redirect_mode(config, config->redirect_mode);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* metacopy feature with upper requires redirect_dir=on */
|
||||||
|
if (config->upperdir && config->metacopy && !config->redirect_dir) {
|
||||||
|
pr_warn("overlayfs: metadata only copy up requires \"redirect_dir=on\", falling back to metacopy=off.\n");
|
||||||
|
config->metacopy = false;
|
||||||
|
} else if (config->metacopy && !config->redirect_follow) {
|
||||||
|
pr_warn("overlayfs: metadata only copy up requires \"redirect_dir=follow\" on non-upper mount, falling back to metacopy=off.\n");
|
||||||
|
config->metacopy = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OVL_WORKDIR_NAME "work"
|
#define OVL_WORKDIR_NAME "work"
|
||||||
|
@ -1013,7 +1047,8 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath)
|
||||||
if (err) {
|
if (err) {
|
||||||
ofs->noxattr = true;
|
ofs->noxattr = true;
|
||||||
ofs->config.index = false;
|
ofs->config.index = false;
|
||||||
pr_warn("overlayfs: upper fs does not support xattr, falling back to index=off.\n");
|
ofs->config.metacopy = false;
|
||||||
|
pr_warn("overlayfs: upper fs does not support xattr, falling back to index=off and metacopy=off.\n");
|
||||||
err = 0;
|
err = 0;
|
||||||
} else {
|
} else {
|
||||||
vfs_removexattr(ofs->workdir, OVL_XATTR_OPAQUE);
|
vfs_removexattr(ofs->workdir, OVL_XATTR_OPAQUE);
|
||||||
|
@ -1035,7 +1070,6 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath)
|
||||||
pr_warn("overlayfs: NFS export requires \"index=on\", falling back to nfs_export=off.\n");
|
pr_warn("overlayfs: NFS export requires \"index=on\", falling back to nfs_export=off.\n");
|
||||||
ofs->config.nfs_export = false;
|
ofs->config.nfs_export = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mnt_drop_write(mnt);
|
mnt_drop_write(mnt);
|
||||||
return err;
|
return err;
|
||||||
|
@ -1346,6 +1380,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
ofs->config.index = ovl_index_def;
|
ofs->config.index = ovl_index_def;
|
||||||
ofs->config.nfs_export = ovl_nfs_export_def;
|
ofs->config.nfs_export = ovl_nfs_export_def;
|
||||||
ofs->config.xino = ovl_xino_def();
|
ofs->config.xino = ovl_xino_def();
|
||||||
|
ofs->config.metacopy = ovl_metacopy_def;
|
||||||
err = ovl_parse_opt((char *) data, &ofs->config);
|
err = ovl_parse_opt((char *) data, &ofs->config);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
@ -1416,6 +1451,11 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ofs->config.metacopy && ofs->config.nfs_export) {
|
||||||
|
pr_warn("overlayfs: NFS export is not supported with metadata only copy up, falling back to nfs_export=off.\n");
|
||||||
|
ofs->config.nfs_export = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (ofs->config.nfs_export)
|
if (ofs->config.nfs_export)
|
||||||
sb->s_export_op = &ovl_export_operations;
|
sb->s_export_op = &ovl_export_operations;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user