NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/45700: /chroot/proc/mounts exposes out-of-chroot pathnames
The following reply was made to PR kern/45700; it has been noted by GNATS.
From: Taylor R Campbell <campbell+netbsd%mumble.net@localhost>
To: matthew green <mrg%eterna.com.au@localhost>
Cc: gnats-bugs%NetBSD.org@localhost, kern-bug-people%netbsd.org@localhost,
gnats-admin%netbsd.org@localhost,
netbsd-bugs%netbsd.org@localhost
Subject: Re: kern/45700: /chroot/proc/mounts exposes out-of-chroot pathnames
Date: Sun, 11 Dec 2011 00:13:28 +0000
Date: Fri, 9 Dec 2011 09:54:36 +0000
From: Taylor R Campbell <campbell%mumble.net@localhost>
Might work just to make procfs_domounts use dostatvfs rather than
reading from mp->mnt_stat directly. I'll look into this at some point
if nobody beats me to it.
The following patch seems to almost work. It doesn't fake an entry
for the root file system if appropriate. Not sure why not, but I
don't want to reboot again at the moment to futz with it; I'll peer
closer at it later.
Index: procfs_linux.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/procfs/procfs_linux.c,v
retrieving revision 1.61
diff -p -u -r1.61 procfs_linux.c
--- procfs_linux.c 4 Sep 2011 17:32:10 -0000 1.61
+++ procfs_linux.c 11 Dec 2011 00:07:23 -0000
@@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_linux
#include <sys/mount.h>
#include <sys/conf.h>
#include <sys/sysctl.h>
+#include <sys/filedesc.h>
#include <miscfs/procfs/procfs.h>
@@ -556,53 +557,81 @@ out:
return error;
}
+
+/*
+ * Append a formatted mount entry for the mount point mp to *mtab
+ * starting at *mtabsz, growing it and adding the length of the entry
+ * to *mtabsz. sfs is mp's vfs statistics structure; bf is a temporary
+ * buffer of size LBFSZ.
+ */
+static void
+procfs_format_mount(struct mount *mp, struct statvfs *sfs, char *bf,
+ char **mtab, size_t *mtabsz)
+{
+ const char *fsname;
+ size_t len;
+
+ /* Linux uses different names for some filesystems. */
+ fsname = sfs->f_fstypename;
+ if (strcmp(fsname, "procfs") == 0)
+ fsname = "proc";
+ else if (strcmp(fsname, "ext2fs") == 0)
+ fsname = "ext2";
+
+ len = snprintf(bf, LBFSZ, "%s %s %s %s%s%s%s%s%s 0 0\n",
+ sfs->f_mntfromname,
+ sfs->f_mntonname,
+ fsname,
+ (mp->mnt_flag & MNT_RDONLY) ? "ro" : "rw",
+ (mp->mnt_flag & MNT_NOSUID) ? ",nosuid" : "",
+ (mp->mnt_flag & MNT_NOEXEC) ? ",noexec" : "",
+ (mp->mnt_flag & MNT_NODEV) ? ",nodev" : "",
+ (mp->mnt_flag & MNT_SYNCHRONOUS) ? ",sync" : "",
+ (mp->mnt_flag & MNT_NOATIME) ? ",noatime" : "");
+
+ *mtab = realloc(*mtab, *mtabsz + len, M_TEMP, M_WAITOK);
+ memcpy(*mtab + *mtabsz, bf, len);
+ *mtabsz += len;
+}
+
int
procfs_domounts(struct lwp *curl, struct proc *p,
struct pfsnode *pfs, struct uio *uio)
{
char *bf, *mtab = NULL;
- const char *fsname;
- size_t len, mtabsz = 0;
+ size_t mtabsz = 0;
struct mount *mp, *nmp;
- struct statvfs *sfs;
+ struct statvfs sfs;
int error = 0;
+ bool root = false;
bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
+
mutex_enter(&mountlist_lock);
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
mp = nmp) {
- if (vfs_busy(mp, &nmp)) {
+ if (vfs_busy(mp, &nmp))
continue;
- }
-
- sfs = &mp->mnt_stat;
- /* Linux uses different names for some filesystems */
- fsname = sfs->f_fstypename;
- if (strcmp(fsname, "procfs") == 0)
- fsname = "proc";
- else if (strcmp(fsname, "ext2fs") == 0)
- fsname = "ext2";
-
- len = snprintf(bf, LBFSZ, "%s %s %s %s%s%s%s%s%s 0 0\n",
- sfs->f_mntfromname,
- sfs->f_mntonname,
- fsname,
- (mp->mnt_flag & MNT_RDONLY) ? "ro" : "rw",
- (mp->mnt_flag & MNT_NOSUID) ? ",nosuid" : "",
- (mp->mnt_flag & MNT_NOEXEC) ? ",noexec" : "",
- (mp->mnt_flag & MNT_NODEV) ? ",nodev" : "",
- (mp->mnt_flag & MNT_SYNCHRONOUS) ? ",sync" : "",
- (mp->mnt_flag & MNT_NOATIME) ? ",noatime" : ""
- );
-
- mtab = realloc(mtab, mtabsz + len, M_TEMP, M_WAITOK);
- memcpy(mtab + mtabsz, bf, len);
- mtabsz += len;
+ if (dostatvfs(mp, &sfs, curl, MNT_NOWAIT, 0) == 0) {
+ procfs_format_mount(mp, &sfs, bf, &mtab, &mtabsz);
+ root |= (strcmp(sfs.f_mntonname, "/") == 0);
+ }
vfs_unbusy(mp, false, &nmp);
}
mutex_exit(&mountlist_lock);
+
+ /*
+ * If we are inside a chroot that is not itself a mount point,
+ * fake a root entry.
+ */
+ if (!root && p->p_cwdi->cwdi_rdir) {
+ mp = p->p_cwdi->cwdi_rdir->v_mount;
+ if (dostatvfs(mp, &sfs, curl, MNT_NOWAIT, 1) == 0)
+ procfs_format_mount(mp, &sfs, bf, &mtab, &mtabsz);
+ }
+
free(bf, M_TEMP);
if (mtabsz > 0) {
Home |
Main Index |
Thread Index |
Old Index