Casinos Not On GamstopNon Gamstop CasinosCasinos Not On GamstopOnline Casinos UKNon Gamstop Casino
19th Sep 1999 [SBWID-122]
COMMAND
	    kernel
SYSTEMS AFFECTED
	    FreeBSD  3.2  and  earlier,  FreeBSD-current before the correction
	    date,  FreeBSD  3.2-stable  before  the  correction  date, FreeBSD
	    2.2.8-stable before the correction date.
PROBLEM
	    Following is based on FreeBSD Security Advisory.  As a  diagnostic
	    aid to help  programmers find bugs  in their programs,  the system
	    creates  core  files  when  an  illegal instruction or other fatal
	    error happens.  A flaw in the kernel allowed it to follow symbolic
	    links when creating core files.   The fts library functions had  a
	    flaw in them where which would  lead to a core dump when  periodic
	    ran  the  security  checking  scripts  (or  other  scripts   which
	    traverse  trees  that  can  be  controlled by users).  periodic(3)
	    should limit core size to zero  to disable core dumps while it  is
	    executing commands, but does not  do so.  In addition,  the kernel
	    should not follow symbolic links.
	    All  three  of  these  problems  caused  a  situation where it was
	    possible for an  attacker could create  or overwrite an  arbitrary
	    file  on  the  system  with  a  moderate degree of controll of its
	    contents to cause a problem.  Local users could gain root access.
SOLUTION
	    Corrected in:
	
	        FreeBSD-3.3 RELEASE
	        FreeBSD-current as of 1999/08/26
	        FreeBSD-3.2-stable as of 1999/08/26
	        FreeBSD-2.2.8-stable as of 1999/08/29
	        The FreeBSD-3.3-RC series of releases are not affected.
	
	    One  can  workaround  this  problem  by  preventing core dumps for
	    periodic.   This  solution  is  less  than  completely satisfying,
	    since it only plugs the known  exploit hole.  None the less,  this
	    may  provide  a  short  term  stopgap  solution until a new kernel
	    and/or userland can be installed.
	
	        # mv /usr/sbin/periodic /usr/sbin/periodic.bin
	        # cat > /usr/sbin/periodic
	        #!/bin/sh
	        ulimit -c 0
	        /usr/sbin/periodic.bin $*
	        ^D
	        # chmod 555 /usr/sbin/periodic
	
	    Another  alternative  would  be  to  update  the fts routines to a
	    version  newer  than  1999/09/02  (for  -current or 3.3-stable) or
	    1999/09/04 (for  2.2.8-stable).   However, this  requires that you
	    rebuild via "make world" to take effect.  Please note: there is  a
	    separate advisory describing the fts problem and solution.  Please
	    see:
	
	        http://oliver.efri.hr/~crv/security/bugs/BSD/libc7.html
	
	    for additional information about the fts patch.
	    Apply the following  patches to your  kernel.  They  will disallow
	    following symbolic links when creating core files.  This will stop
	    this attack, and all similar  such attacks.  Here's the  patch for
	    freebsd-current:
	
	    *** kern/imgact_elf.c	1999/07/09 19:10:14	1.61
	    --- kern/imgact_elf.c	1999/08/26 17:32:48	1.62
	    ***************
	    *** 722,729 ****
	        if (name == NULL)
		        return (EFAULT);	/* XXX -- not the best error */
	    ! 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
	    ! 	error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR);
	        free(name, M_TEMP);
	        if (error)
		        return (error);
	    --- 722,729 ----
	        if (name == NULL)
		        return (EFAULT);	/* XXX -- not the best error */
	    ! 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
	    ! 	error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
	        free(name, M_TEMP);
	        if (error)
		        return (error);
	    *** kern/imgact_aout.c	1999/05/17 00:53:36	1.52
	    --- kern/imgact_aout.c	1999/08/26 17:32:48	1.53
	    ***************
	    *** 264,271 ****
	        name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
	        if (name == NULL)
		        return (EFAULT);	/* XXX -- not the best error */
	    ! 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
	    ! 	error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR);
	        free(name, M_TEMP);
	        if (error)
		        return (error);
	    --- 264,271 ----
	        name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
	        if (name == NULL)
		        return (EFAULT);	/* XXX -- not the best error */
	    ! 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
	    ! 	error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
	        free(name, M_TEMP);
	        if (error)
		        return (error);
	
	    Here's the patch for freebsd-3.2-stable:
	
	    *** kern/imgact_elf.c	1999/07/15 13:01:54	1.44.2.4
	    --- kern/imgact_elf.c	1999/08/26 17:35:03	1.44.2.5
	    ***************
	    *** 699,706 ****
	        if (name == NULL)
		        return (EFAULT);	/* XXX -- not the best error */
	    ! 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
	    ! 	error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR);
	        free(name, M_TEMP);
	        if (error)
		        return (error);
	    --- 699,706 ----
	        if (name == NULL)
		        return (EFAULT);	/* XXX -- not the best error */
	    ! 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
	    ! 	error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
	        free(name, M_TEMP);
	        if (error)
		        return (error);
	    *** kern/imgact_aout.c	1999/04/14 04:55:22	1.44.2.1
	    --- kern/imgact_aout.c	1999/08/26 17:35:02	1.44.2.2
	    ***************
	    *** 259,266 ****
	        name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
	        if (name == NULL)
		        return (EFAULT);	/* XXX -- not the best error */
	    ! 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
	    ! 	error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR);
	        free(name, M_TEMP);
	        if (error)
		        return (error);
	    --- 259,266 ----
	        name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
	        if (name == NULL)
		        return (EFAULT);	/* XXX -- not the best error */
	    ! 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
	    ! 	error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
	        free(name, M_TEMP);
	        if (error)
		        return (error);
	
	    Here's the patch for FreeBSD-2.2.8-stable
	
	    *** sys/LINK/fcntl.h	Wed Dec 18 05:08:08 1996
	    --- sys/fcntl.h	Fri Aug 27 14:39:26 1999
	    ***************
	    *** 84,89 ****
	    --- 84,90 ----
	      #define	O_EXLOCK	0x0020		/* open with exclusive file lock */
	      #define	O_ASYNC		0x0040		/* signal pgrp when data ready */
	      #define	O_FSYNC		0x0080		/* synchronous writes */
	    + #define	O_NOFOLLOW	0x0100		/* don't follow symlinks */
	      #endif
	      #define	O_CREAT		0x0200		/* create if nonexistent */
	      #define	O_TRUNC		0x0400		/* truncate to zero length */
	    *** kern/LINK/kern_sig.c	Sat Dec 21 10:57:24 1996
	    --- kern/kern_sig.c	Fri Aug 27 14:38:25 1999
	    ***************
	    *** 1241,1249 ****
		    p->p_rlimit[RLIMIT_CORE].rlim_cur)
		        return (EFAULT);
	        sprintf(name, "%s.core", p->p_comm);
	    ! 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
	        if ((error = vn_open(&nd,
	    ! 	    O_CREAT | FWRITE, S_IRUSR | S_IWUSR)))
		        return (error);
	        vp = nd.ni_vp;
	    --- 1241,1249 ----
		    p->p_rlimit[RLIMIT_CORE].rlim_cur)
		        return (EFAULT);
	        sprintf(name, "%s.core", p->p_comm);
	    ! 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
	        if ((error = vn_open(&nd,
	    ! 	    O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR)))
		        return (error);
	        vp = nd.ni_vp;
	    *** kern/LINK/vfs_vnops.c	Sat Mar  8 07:16:18 1997
	    --- kern/vfs_vnops.c	Fri Aug 27 14:37:01 1999
	    ***************
	    *** 87,93 ****
	        if (fmode & O_CREAT) {
		        ndp->ni_cnd.cn_nameiop = CREATE;
		        ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
	    ! 		if ((fmode & O_EXCL) == 0)
			        ndp->ni_cnd.cn_flags |= FOLLOW;
		        error = namei(ndp);
		        if (error)
	    --- 87,93 ----
	        if (fmode & O_CREAT) {
		        ndp->ni_cnd.cn_nameiop = CREATE;
		        ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
	    ! 		if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0)
			        ndp->ni_cnd.cn_flags |= FOLLOW;
		        error = namei(ndp);
		        if (error)
	    ***************
	    *** 119,125 ****
		        }
	        } else {
		        ndp->ni_cnd.cn_nameiop = LOOKUP;
	    ! 		ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF;
		        error = namei(ndp);
		        if (error)
			        return (error);
	    --- 119,126 ----
		        }
	        } else {
		        ndp->ni_cnd.cn_nameiop = LOOKUP;
	    ! 		ndp->ni_cnd.cn_flags =
	    ! 		    ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF;
		        error = namei(ndp);
		        if (error)
			        return (error);
	    *** kern/LINK/vfs_syscalls.c	Wed Aug  4 12:44:30 1999
	    --- kern/vfs_syscalls.c	Sat Aug 28 10:48:51 1999
	    ***************
	    *** 694,699 ****
	    --- 694,701 ----
	        flags = FFLAGS(uap->flags);
	        if ((flags & FREAD + FWRITE) == 0)
		        return (EINVAL);
	    + 	if (flags & O_NOFOLLOW)
	    + 		flags &= ~O_NOFOLLOW;
	        error = falloc(p, &nfp, &indx);
	        if (error)
		        return (error);
	
	

Internet highlights