Author: trasz
Date: Wed Apr 15 09:13:11 2015
New Revision: 281551
URL: https://svnweb.freebsd.org/changeset/base/281551

Log:
  Rewrite linprocfs_domtab() as a wrapper around kern_getfsstat(). This
  adds missing jail and MAC checks.
  
  Differential Revision:        https://reviews.freebsd.org/D2193
  Reviewed by:  kib@
  MFC after:    1 month
  Sponsored by: The FreeBSD Foundation

Modified:
  head/sys/compat/freebsd32/freebsd32_misc.c
  head/sys/compat/linprocfs/linprocfs.c
  head/sys/kern/vfs_syscalls.c
  head/sys/sys/syscallsubr.h

Modified: head/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_misc.c  Wed Apr 15 09:09:20 2015        
(r281550)
+++ head/sys/compat/freebsd32/freebsd32_misc.c  Wed Apr 15 09:13:11 2015        
(r281551)
@@ -253,9 +253,8 @@ freebsd4_freebsd32_getfsstat(struct thre
 
        count = uap->bufsize / sizeof(struct statfs32);
        size = count * sizeof(struct statfs);
-       error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
+       error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE, 
uap->flags);
        if (size > 0) {
-               count = td->td_retval[0];
                sp = buf;
                while (count > 0 && error == 0) {
                        copy_statfs(sp, &stat32);
@@ -266,6 +265,8 @@ freebsd4_freebsd32_getfsstat(struct thre
                }
                free(buf, M_TEMP);
        }
+       if (error == 0)
+               td->td_retval[0] = count;
        return (error);
 }
 #endif

Modified: head/sys/compat/linprocfs/linprocfs.c
==============================================================================
--- head/sys/compat/linprocfs/linprocfs.c       Wed Apr 15 09:09:20 2015        
(r281550)
+++ head/sys/compat/linprocfs/linprocfs.c       Wed Apr 15 09:13:11 2015        
(r281551)
@@ -53,10 +53,10 @@ __FBSDID("$FreeBSD$");
 #include <sys/filedesc.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
+#include <sys/limits.h>
 #include <sys/linker.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
-#include <sys/mount.h>
 #include <sys/msg.h>
 #include <sys/mutex.h>
 #include <sys/namei.h>
@@ -67,6 +67,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/sem.h>
 #include <sys/smp.h>
 #include <sys/socket.h>
+#include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
 #include <sys/systm.h>
 #include <sys/time.h>
@@ -326,11 +327,12 @@ static int
 linprocfs_domtab(PFS_FILL_ARGS)
 {
        struct nameidata nd;
-       struct mount *mp;
        const char *lep;
        char *dlep, *flep, *mntto, *mntfrom, *fstype;
        size_t lep_len;
        int error;
+       struct statfs *buf, *sp;
+       size_t count;
 
        /* resolve symlinks etc. in the emulation tree prefix */
        NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
@@ -344,20 +346,26 @@ linprocfs_domtab(PFS_FILL_ARGS)
        }
        lep_len = strlen(lep);
 
-       mtx_lock(&mountlist_mtx);
-       error = 0;
-       TAILQ_FOREACH(mp, &mountlist, mnt_list) {
+       buf = NULL;
+       error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count,
+           UIO_SYSSPACE, MNT_WAIT);
+       if (error != 0) {
+               free(buf, M_TEMP);
+               free(flep, M_TEMP);
+               return (error);
+       }
+
+       for (sp = buf; count > 0; sp++, count--) {
                /* determine device name */
-               mntfrom = mp->mnt_stat.f_mntfromname;
+               mntfrom = sp->f_mntfromname;
 
                /* determine mount point */
-               mntto = mp->mnt_stat.f_mntonname;
-               if (strncmp(mntto, lep, lep_len) == 0 &&
-                   mntto[lep_len] == '/')
+               mntto = sp->f_mntonname;
+               if (strncmp(mntto, lep, lep_len) == 0 && mntto[lep_len] == '/')
                        mntto += lep_len;
 
                /* determine fs type */
-               fstype = mp->mnt_stat.f_fstypename;
+               fstype = sp->f_fstypename;
                if (strcmp(fstype, pn->pn_info->pi_name) == 0)
                        mntfrom = fstype = "proc";
                else if (strcmp(fstype, "procfs") == 0)
@@ -365,16 +373,16 @@ linprocfs_domtab(PFS_FILL_ARGS)
 
                if (strcmp(fstype, "linsysfs") == 0) {
                        sbuf_printf(sb, "/sys %s sysfs %s", mntto,
-                           mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
+                           sp->f_flags & MNT_RDONLY ? "ro" : "rw");
                } else {
                        /* For Linux msdosfs is called vfat */
                        if (strcmp(fstype, "msdosfs") == 0)
                                fstype = "vfat";
                        sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
-                           mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
+                           sp->f_flags & MNT_RDONLY ? "ro" : "rw");
                }
 #define ADD_OPTION(opt, name) \
-       if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
+       if (sp->f_flags & (opt)) sbuf_printf(sb, "," name);
                ADD_OPTION(MNT_SYNCHRONOUS,     "sync");
                ADD_OPTION(MNT_NOEXEC,          "noexec");
                ADD_OPTION(MNT_NOSUID,          "nosuid");
@@ -387,7 +395,8 @@ linprocfs_domtab(PFS_FILL_ARGS)
                /* a real Linux mtab will also show NFS options */
                sbuf_printf(sb, " 0 0\n");
        }
-       mtx_unlock(&mountlist_mtx);
+
+       free(buf, M_TEMP);
        free(flep, M_TEMP);
        return (error);
 }

Modified: head/sys/kern/vfs_syscalls.c
==============================================================================
--- head/sys/kern/vfs_syscalls.c        Wed Apr 15 09:09:20 2015        
(r281550)
+++ head/sys/kern/vfs_syscalls.c        Wed Apr 15 09:13:11 2015        
(r281551)
@@ -434,9 +434,14 @@ sys_getfsstat(td, uap)
                int flags;
        } */ *uap;
 {
+       size_t count;
+       int error;
 
-       return (kern_getfsstat(td, &uap->buf, uap->bufsize, UIO_USERSPACE,
-           uap->flags));
+       error = kern_getfsstat(td, &uap->buf, uap->bufsize, &count,
+           UIO_USERSPACE, uap->flags);
+       if (error == 0)
+               td->td_retval[0] = count;
+       return (error);
 }
 
 /*
@@ -446,7 +451,7 @@ sys_getfsstat(td, uap)
  */
 int
 kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
-    enum uio_seg bufseg, int flags)
+    size_t *countp, enum uio_seg bufseg, int flags)
 {
        struct mount *mp, *nmp;
        struct statfs *sfsp, *sp, sb;
@@ -533,9 +538,9 @@ kern_getfsstat(struct thread *td, struct
        }
        mtx_unlock(&mountlist_mtx);
        if (sfsp && count > maxcount)
-               td->td_retval[0] = maxcount;
+               *countp = maxcount;
        else
-               td->td_retval[0] = count;
+               *countp = count;
        return (0);
 }
 
@@ -624,9 +629,9 @@ freebsd4_getfsstat(td, uap)
 
        count = uap->bufsize / sizeof(struct ostatfs);
        size = count * sizeof(struct statfs);
-       error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
+       error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE,
+           uap->flags);
        if (size > 0) {
-               count = td->td_retval[0];
                sp = buf;
                while (count > 0 && error == 0) {
                        cvtstatfs(sp, &osb);
@@ -637,6 +642,8 @@ freebsd4_getfsstat(td, uap)
                }
                free(buf, M_TEMP);
        }
+       if (error == 0)
+               td->td_retval[0] = count;
        return (error);
 }
 

Modified: head/sys/sys/syscallsubr.h
==============================================================================
--- head/sys/sys/syscallsubr.h  Wed Apr 15 09:09:20 2015        (r281550)
+++ head/sys/sys/syscallsubr.h  Wed Apr 15 09:13:11 2015        (r281551)
@@ -104,7 +104,7 @@ int kern_futimens(struct thread *td, int
 int    kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
            long *basep, ssize_t *residp, enum uio_seg bufseg);
 int    kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
-           enum uio_seg bufseg, int flags);
+           size_t *countp, enum uio_seg bufseg, int flags);
 int    kern_getitimer(struct thread *, u_int, struct itimerval *);
 int    kern_getppid(struct thread *);
 int    kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to