Re: jail getfsstat patches.

From: Julian Elischer <julian_at_elischer.org>
Date: Tue, 29 Jun 2004 12:43:16 -0700 (PDT)
On Mon, 28 Jun 2004, Pawel Jakub Dawidek wrote:

> On Sun, Jun 27, 2004 at 11:40:48PM -0700, Julian Elischer wrote:
> +> > On Sun, Jun 27, 2004 at 08:59:32AM +0200, Pawel Jakub Dawidek wrote:
> +> > +> If you give me a few days (maybe I'll be ready today) I'll try to prepare
> +> > +> patch to commit so we can review it together.
> +> > 
> +> > Ok, here it goes:
> +> > 
> +> > 	http://people.freebsd.org/~pjd/patches/jail_enforce_statfs.patch
> +> > 
> +> > As you can see, all mac_check_mount_stat() calls are placed after a
> +> > prison_canseemount() call, so we can considern moving mac_check_mount_stat()
> +> > to prison_canseemount() function.
> +> > 
> +> 
> +>  The patch looks good to me but I don't have a 5.x machine with jails at
> +> the moment (I may try set up a small jail tomorrow to test it).
> +> 
> +> do you have a 4.x version?
> 
> I don't have 4.x boxes, so I can't prepare one for 4.x. Could you try to
> port it? It should be easy.

I was looking at the original patch for 4.x (the one that is a kld
module).
It has a serious flaw in that if teh buf pointer is NULL it is supposed
to return teh number of filesystems, but it returns teh REAL number of
filesystems instead of the number in the jail.

IN ADDITION it writes directly to user space instead of writing
with copyout()..

here is my (I hope) fixed version...


jail_getfsstat(register struct proc *p, register struct getfsstat_args
*uap)
{
        register struct mount   *mp, *nmp;
        struct mount    *cmp;
        register struct statfs  *sp;
        struct statfs   *tsp;
        caddr_t sfsp;  
        long    count, maxcount, error;
        static char     chrootdir[MAXPATHLEN];
        int     ret;   
        int     copy;
        struct statfs dummystatfs;

        if (p->p_prison == NULL)
                return old_getfsstat(p, uap);

        if ((ret = getchrootdir(p, chrootdir, sizeof chrootdir)) != 0)
                return (ret);

        if ((ret = chrmp(p, "/", &cmp)) != 0)
                return (ret);

        maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
        sfsp = (caddr_t)SCARG(uap, buf);
        count = 0;
        simple_lock(&mountlist_slock);
	tsp = &dummystatfs;

        for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {  
                if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
                        nmp = TAILQ_NEXT(mp, mnt_list);
                        continue;
                }
                sp = &mp->mnt_stat;
                /*
                 * If MNT_NOWAIT or MNT_LAZY is specified, do not
                 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
                 * overrides MNT_WAIT.
                 */
                if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
                    (SCARG(uap, flags) & MNT_WAIT)) &&
                    (error = VFS_STATFS(mp, sp, p))) {
                        simple_lock(&mountlist_slock);
                        nmp = TAILQ_NEXT(mp, mnt_list);
                        vfs_unbusy(mp, p);
                        continue;
                }
                bcopy(sp, tsp, sizeof(*sp));
                copy = 1;
                if (cmp == mp) {
                        strcpy(tsp->f_mntonname, "/");
                } else if (!parsepath(tsp->f_mntonname, chrootdir)) {
                        copy = 0;
                }
                if (copy) {
                	if (sfsp != NULL && count < maxcount) {
                        	tsp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
                        	error = copyout((caddr_t)tsp, sfsp,
sizeof(*sp));
                        	if (error) {
                                	vfs_unbusy(mp, p);
                                	return (error);
                        	}
                        	sfsp += sizeof(*sp);
			}
			count++
                }
                simple_lock(&mountlist_slock);
                nmp = TAILQ_NEXT(mp, mnt_list);
                vfs_unbusy(mp, p);
        }
        simple_unlock(&mountlist_slock);
        if (sfsp && count > maxcount)
                p->p_retval[0] = maxcount;
        else
                p->p_retval[0] = count;
        return (0);
}



> 
> -- 
> Pawel Jakub Dawidek                       http://www.FreeBSD.org
> pjd_at_FreeBSD.org                           http://garage.freebsd.pl
> FreeBSD committer                         Am I Evil? Yes, I Am!
> 
Received on Tue Jun 29 2004 - 17:43:32 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:59 UTC