Add support for mounting single files in nullfs

My main use-case for this is to support mounting config files and secrets
into OCI containers. My current workaround copies the files into the
container which is messy and risks secrets leaking into container images
if the cleanup fails.

Reviewed by:	mjg, kib
Tested by:	pho
Differential Revision: https://reviews.freebsd.org/D37478
This commit is contained in:
Doug Rabson 2022-11-07 16:56:09 +00:00
parent 5cfacab132
commit a3f714c4ff
5 changed files with 67 additions and 5 deletions

View file

@ -139,6 +139,20 @@ checkpath(const char *path, char *resolved)
return (0);
}
int
checkpath_allow_file(const char *path, char *resolved)
{
struct stat sb;
if (realpath(path, resolved) == NULL || stat(resolved, &sb) != 0)
return (1);
if (!S_ISDIR(sb.st_mode) && !S_ISREG(sb.st_mode)) {
errno = ENOTDIR;
return (1);
}
return (0);
}
void
build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val,
size_t len)

View file

@ -103,6 +103,7 @@ struct mntopt {
void getmntopts(const char *, const struct mntopt *, int *, int *);
void rmslashes(char *, char *);
int checkpath(const char *, char resolved_path[]);
int checkpath_allow_file(const char *, char resolved_path[]);
extern int getmnt_silent;
void build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, size_t len);
void build_iovec_argf(struct iovec **iov, int *iovlen, const char *name, const char *fmt, ...);

View file

@ -89,6 +89,7 @@ struct statfs *getmntpt(const char *);
int hasopt(const char *, const char *);
int ismounted(struct fstab *, struct statfs *, int);
int isremountable(const char *);
int allow_file_mount(const char *);
void mangle(char *, struct cpa *);
char *update_options(char *, char *, int);
int mountfs(const char *, const char *, const char *,
@ -502,6 +503,15 @@ isremountable(const char *vfsname)
return (0);
}
int
allow_file_mount(const char *vfsname)
{
if (strcmp(vfsname, "nullfs") == 0)
return (1);
return (0);
}
int
hasopt(const char *mntopts, const char *option)
{
@ -548,9 +558,16 @@ mountfs(const char *vfstype, const char *spec, const char *name, int flags,
static struct cpa mnt_argv;
/* resolve the mountpoint with realpath(3) */
if (checkpath(name, mntpath) != 0) {
xo_warn("%s", mntpath);
return (1);
if (allow_file_mount(vfstype)) {
if (checkpath_allow_file(name, mntpath) != 0) {
xo_warn("%s", mntpath);
return (1);
}
} else {
if (checkpath(name, mntpath) != 0) {
xo_warn("%s", mntpath);
return (1);
}
}
name = mntpath;

View file

@ -64,6 +64,17 @@ but in other respects it is indistinguishable from the original.
.Pp
The
.Nm
utility supports mounting both directories and single files.
Both
.Ar target
and
.Ar mount_point
must be the same type.
Mounting directories to files or files to
directories is not supported.
.Pp
The
.Nm
file system differs from a traditional
loopback file system in two respects: it is implemented using
a stackable layers techniques, and its

View file

@ -48,6 +48,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <err.h>
@ -61,6 +62,14 @@ static const char rcsid[] =
static void usage(void) __dead2;
static int
stat_realpath(const char *path, char *resolved, struct stat *sbp)
{
if (realpath(path, resolved) == NULL || stat(resolved, sbp) != 0)
return (1);
return (0);
}
int
main(int argc, char *argv[])
{
@ -71,6 +80,8 @@ main(int argc, char *argv[])
char errmsg[255];
int ch, iovlen;
char nullfs[] = "nullfs";
struct stat target_stat;
struct stat mountpoint_stat;
iov = NULL;
iovlen = 0;
@ -98,10 +109,18 @@ main(int argc, char *argv[])
usage();
/* resolve target and mountpoint with realpath(3) */
if (checkpath(argv[0], target) != 0)
if (stat_realpath(argv[0], target, &target_stat) != 0)
err(EX_USAGE, "%s", target);
if (checkpath(argv[1], mountpoint) != 0)
if (stat_realpath(argv[1], mountpoint, &mountpoint_stat) != 0)
err(EX_USAGE, "%s", mountpoint);
if (!S_ISDIR(target_stat.st_mode) && !S_ISREG(target_stat.st_mode))
errx(EX_USAGE, "%s: must be either a file or directory",
target);
if ((target_stat.st_mode & S_IFMT) !=
(mountpoint_stat.st_mode & S_IFMT))
errx(EX_USAGE,
"%s: must be same type as %s (file or directory)",
mountpoint, target);
build_iovec(&iov, &iovlen, "fstype", nullfs, (size_t)-1);
build_iovec(&iov, &iovlen, "fspath", mountpoint, (size_t)-1);