3571e53040
patches for easier mirroring, to eliminate a special copy, to make www.freebsd.org/security a full copy of security.freebsd.org and be eventually be the same. For now files are just sitting there. The symlinks are missing. Discussed on: www (repository location) Discussed with: simon (so)
445 lines
15 KiB
Text
445 lines
15 KiB
Text
-----BEGIN PGP SIGNED MESSAGE-----
|
|
|
|
|
|
=============================================================================
|
|
FreeBSD-SA-97:04 Security Advisory
|
|
FreeBSD, Inc.
|
|
|
|
Topic: security compromise via procfs
|
|
|
|
Category: core
|
|
Module: procfs
|
|
Announced: 1997-08-19
|
|
Affects: FreeBSD 2.1.*, FreeBSD 2.2.*,
|
|
FreeBSD-stable and FreeBSD-current
|
|
before 1997/08/12 suffer from this problem.
|
|
Corrected: FreeBSD-current as of 1997/08/12
|
|
FreeBSD-stable as of 1997/08/12
|
|
FreeBSD 2.1-stable as of 1997/08/25
|
|
FreeBSD only: no (also other BSD systems may be affected)
|
|
|
|
Patches: ftp://freebsd.org/pub/CERT/patches/SA-97:04/
|
|
|
|
=============================================================================
|
|
|
|
I. Background
|
|
|
|
Procfs provides a filesystem interface to processes on a system.
|
|
Among others it is used by ps(1) and gdb(1).
|
|
|
|
II. Problem Description
|
|
|
|
A problem exists in the procfs kernel code that allows processes
|
|
to write memory of other processes where it should have been prohibited.
|
|
|
|
III. Impact
|
|
|
|
The hole can be used by any user on the system to gain root privileges.
|
|
|
|
IV. Workaround
|
|
|
|
A workaround is to disable the mounting of procfs. To achieve this,
|
|
edit the file /etc/fstab and put a '#' in front of the line
|
|
proc /proc procfs rw 0 0
|
|
Note that when you do that, some utilities may either not work anymore
|
|
or have a limited functionality.
|
|
|
|
V. Solution
|
|
|
|
Apply one of the following patches in /usr/src/sys/miscfs/procfs,
|
|
rebuild your kernel, install it and reboot your system.
|
|
|
|
For 2.1 and 2.2 systems:
|
|
|
|
Index: procfs_regs.c
|
|
===================================================================
|
|
RCS file: /home/cvsup/freebsd/CVS/src/sys/miscfs/procfs/procfs_regs.c,v
|
|
retrieving revision 1.3
|
|
retrieving revision 1.3.4.1
|
|
diff -u -r1.3 -r1.3.4.1
|
|
--- procfs_regs.c 1996/01/24 18:41:25 1.3
|
|
+++ procfs_regs.c 1997/08/12 04:45:25 1.3.4.1
|
|
@@ -36,7 +36,7 @@
|
|
*
|
|
* @(#)procfs_regs.c 8.3 (Berkeley) 1/27/94
|
|
*
|
|
- * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
+ * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
@@ -62,6 +62,8 @@
|
|
char *kv;
|
|
int kl;
|
|
|
|
+ if (!CHECKIO(curp, p))
|
|
+ return EPERM;
|
|
kl = sizeof(r);
|
|
kv = (char *) &r;
|
|
|
|
Index: procfs.h
|
|
===================================================================
|
|
RCS file: /home/cvsup/freebsd/CVS/src/sys/miscfs/procfs/procfs.h,v
|
|
retrieving revision 1.12
|
|
retrieving revision 1.12.2.1
|
|
diff -u -r1.12 -r1.12.2.1
|
|
--- procfs.h 1996/07/02 13:38:07 1.12
|
|
+++ procfs.h 1997/08/12 04:45:20 1.12.2.1
|
|
@@ -36,7 +36,7 @@
|
|
*
|
|
* @(#)procfs.h 8.6 (Berkeley) 2/3/94
|
|
*
|
|
- * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
+ * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
*/
|
|
|
|
/*
|
|
@@ -83,6 +83,18 @@
|
|
(bcmp((s), (cnp)->cn_nameptr, (len)) == 0))
|
|
|
|
#define KMEM_GROUP 2
|
|
+
|
|
+/*
|
|
+ * Check to see whether access to target process is allowed
|
|
+ * Evaluates to 1 if access is allowed.
|
|
+ */
|
|
+#define CHECKIO(p1, p2) \
|
|
+ ((((p1)->p_cred->pc_ucred->cr_uid == (p2)->p_cred->p_ruid) && \
|
|
+ ((p1)->p_cred->p_ruid == (p2)->p_cred->p_ruid) && \
|
|
+ ((p1)->p_cred->p_svuid == (p2)->p_cred->p_ruid) && \
|
|
+ ((p2)->p_flag & P_SUGID) == 0) || \
|
|
+ (suser((p1)->p_cred->pc_ucred, &(p1)->p_acflag) == 0))
|
|
+
|
|
/*
|
|
* Format of a directory entry in /proc, ...
|
|
* This must map onto struct dirent (see <dirent.h>)
|
|
Index: procfs_mem.c
|
|
===================================================================
|
|
RCS file: /home/cvsup/freebsd/CVS/src/sys/miscfs/procfs/procfs_mem.c,v
|
|
retrieving revision 1.20
|
|
retrieving revision 1.20.2.1
|
|
diff -u -r1.20 -r1.20.2.1
|
|
--- procfs_mem.c 1996/10/24 02:47:05 1.20
|
|
+++ procfs_mem.c 1997/08/12 04:45:23 1.20.2.1
|
|
@@ -37,7 +37,7 @@
|
|
*
|
|
* @(#)procfs_mem.c 8.4 (Berkeley) 1/21/94
|
|
*
|
|
- * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
+ * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
*/
|
|
|
|
/*
|
|
@@ -300,6 +300,23 @@
|
|
if (uio->uio_resid == 0)
|
|
return (0);
|
|
|
|
+ /*
|
|
+ * XXX
|
|
+ * We need to check for KMEM_GROUP because ps is sgid kmem;
|
|
+ * not allowing it here causes ps to not work properly. Arguably,
|
|
+ * this is a bug with what ps does. We only need to do this
|
|
+ * for Pmem nodes, and only if it's reading. This is still not
|
|
+ * good, as it may still be possible to grab illicit data if
|
|
+ * a process somehow gets to be KMEM_GROUP. Note that this also
|
|
+ * means that KMEM_GROUP can't change without editing procfs.h!
|
|
+ * All in all, quite yucky.
|
|
+ */
|
|
+
|
|
+ if (!CHECKIO(curp, p) &&
|
|
+ !(curp->p_cred->pc_ucred->cr_gid == KMEM_GROUP &&
|
|
+ uio->uio_rw == UIO_READ))
|
|
+ return EPERM;
|
|
+
|
|
error = procfs_rwmem(p, uio);
|
|
|
|
return (error);
|
|
Index: procfs_vnops.c
|
|
===================================================================
|
|
RCS file: /home/cvsup/freebsd/CVS/src/sys/miscfs/procfs/procfs_vnops.c,v
|
|
retrieving revision 1.24
|
|
retrieving revision 1.24.2.1
|
|
diff -u -r1.24 -r1.24.2.1
|
|
--- procfs_vnops.c 1996/09/03 14:23:10 1.24
|
|
+++ procfs_vnops.c 1997/08/12 04:45:27 1.24.2.1
|
|
@@ -36,7 +36,7 @@
|
|
*
|
|
* @(#)procfs_vnops.c 8.6 (Berkeley) 2/7/94
|
|
*
|
|
- * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
+ * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
*/
|
|
|
|
/*
|
|
@@ -120,16 +120,21 @@
|
|
struct vop_open_args *ap;
|
|
{
|
|
struct pfsnode *pfs = VTOPFS(ap->a_vp);
|
|
+ struct proc *p1 = ap->a_p, *p2 = PFIND(pfs->pfs_pid);
|
|
+
|
|
+ if (p2 == NULL)
|
|
+ return ENOENT;
|
|
|
|
switch (pfs->pfs_type) {
|
|
case Pmem:
|
|
- if (PFIND(pfs->pfs_pid) == 0)
|
|
- return (ENOENT); /* was ESRCH, jsp */
|
|
-
|
|
if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
|
|
((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE)))
|
|
return (EBUSY);
|
|
|
|
+ if (!CHECKIO(p1, p2) &&
|
|
+ (p1->p_cred->pc_ucred->cr_gid != KMEM_GROUP))
|
|
+ return EPERM;
|
|
+
|
|
|
|
if (ap->a_mode & FWRITE)
|
|
pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
|
|
@@ -176,7 +181,6 @@
|
|
procfs_ioctl(ap)
|
|
struct vop_ioctl_args *ap;
|
|
{
|
|
-
|
|
return (ENOTTY);
|
|
}
|
|
|
|
Index: procfs_fpregs.c
|
|
===================================================================
|
|
RCS file: /home/cvsup/freebsd/CVS/src/sys/miscfs/procfs/procfs_fpregs.c,v
|
|
retrieving revision 1.3
|
|
retrieving revision 1.3.4.1
|
|
diff -u -r1.3 -r1.3.4.1
|
|
--- procfs_fpregs.c 1996/01/24 18:40:56 1.3
|
|
+++ procfs_fpregs.c 1997/08/12 05:24:20 1.3.4.1
|
|
@@ -36,7 +36,7 @@
|
|
*
|
|
* @(#)procfs_fpregs.c 8.1 (Berkeley) 1/27/94
|
|
*
|
|
- * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
+ * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
@@ -62,6 +62,8 @@
|
|
char *kv;
|
|
int kl;
|
|
|
|
+ if (!CHECKIO(curp, p))
|
|
+ return EPERM;
|
|
kl = sizeof(r);
|
|
kv = (char *) &r;
|
|
|
|
For FreeBSd-current systems:
|
|
|
|
Index: procfs_regs.c
|
|
===================================================================
|
|
RCS file: /home/cvsup/freebsd/CVS/src/sys/miscfs/procfs/procfs_regs.c,v
|
|
retrieving revision 1.7
|
|
retrieving revision 1.8
|
|
diff -u -r1.7 -r1.8
|
|
--- procfs_regs.c 1997/08/02 14:32:16 1.7
|
|
+++ procfs_regs.c 1997/08/12 04:34:29 1.8
|
|
@@ -37,7 +37,7 @@
|
|
* @(#)procfs_regs.c 8.4 (Berkeley) 6/15/94
|
|
*
|
|
* From:
|
|
- * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
+ * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
@@ -60,6 +60,8 @@
|
|
char *kv;
|
|
int kl;
|
|
|
|
+ if (!CHECKIO(curp, p))
|
|
+ return EPERM;
|
|
kl = sizeof(r);
|
|
kv = (char *) &r;
|
|
|
|
Index: procfs.h
|
|
===================================================================
|
|
RCS file: /home/cvsup/freebsd/CVS/src/sys/miscfs/procfs/procfs.h,v
|
|
retrieving revision 1.15
|
|
retrieving revision 1.16
|
|
diff -u -r1.15 -r1.16
|
|
--- procfs.h 1997/02/22 09:40:26 1.15
|
|
+++ procfs.h 1997/08/12 04:34:27 1.16
|
|
@@ -37,7 +37,7 @@
|
|
* @(#)procfs.h 8.9 (Berkeley) 5/14/95
|
|
*
|
|
* From:
|
|
- * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
+ * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
*/
|
|
|
|
/*
|
|
@@ -85,6 +85,18 @@
|
|
(bcmp((s), (cnp)->cn_nameptr, (len)) == 0))
|
|
|
|
#define KMEM_GROUP 2
|
|
+
|
|
+/*
|
|
+ * Check to see whether access to target process is allowed
|
|
+ * Evaluates to 1 if access is allowed.
|
|
+ */
|
|
+#define CHECKIO(p1, p2) \
|
|
+ ((((p1)->p_cred->pc_ucred->cr_uid == (p2)->p_cred->p_ruid) && \
|
|
+ ((p1)->p_cred->p_ruid == (p2)->p_cred->p_ruid) && \
|
|
+ ((p1)->p_cred->p_svuid == (p2)->p_cred->p_ruid) && \
|
|
+ ((p2)->p_flag & P_SUGID) == 0) || \
|
|
+ (suser((p1)->p_cred->pc_ucred, &(p1)->p_acflag) == 0))
|
|
+
|
|
/*
|
|
* Format of a directory entry in /proc, ...
|
|
* This must map onto struct dirent (see <dirent.h>)
|
|
Index: procfs_mem.c
|
|
===================================================================
|
|
RCS file: /home/cvsup/freebsd/CVS/src/sys/miscfs/procfs/procfs_mem.c,v
|
|
retrieving revision 1.26
|
|
retrieving revision 1.27
|
|
diff -u -r1.26 -r1.27
|
|
--- procfs_mem.c 1997/08/02 14:32:14 1.26
|
|
+++ procfs_mem.c 1997/08/12 04:34:28 1.27
|
|
@@ -37,7 +37,7 @@
|
|
*
|
|
* @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94
|
|
*
|
|
- * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
+ * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
*/
|
|
|
|
/*
|
|
@@ -276,6 +276,23 @@
|
|
|
|
if (uio->uio_resid == 0)
|
|
return (0);
|
|
+
|
|
+ /*
|
|
+ * XXX
|
|
+ * We need to check for KMEM_GROUP because ps is sgid kmem;
|
|
+ * not allowing it here causes ps to not work properly. Arguably,
|
|
+ * this is a bug with what ps does. We only need to do this
|
|
+ * for Pmem nodes, and only if it's reading. This is still not
|
|
+ * good, as it may still be possible to grab illicit data if
|
|
+ * a process somehow gets to be KMEM_GROUP. Note that this also
|
|
+ * means that KMEM_GROUP can't change without editing procfs.h!
|
|
+ * All in all, quite yucky.
|
|
+ */
|
|
+
|
|
+ if (!CHECKIO(curp, p) &&
|
|
+ !(curp->p_cred->pc_ucred->cr_gid == KMEM_GROUP &&
|
|
+ uio->uio_rw == UIO_READ))
|
|
+ return EPERM;
|
|
|
|
return (procfs_rwmem(p, uio));
|
|
}
|
|
Index: procfs_vnops.c
|
|
===================================================================
|
|
RCS file: /home/cvsup/freebsd/CVS/src/sys/miscfs/procfs/procfs_vnops.c,v
|
|
retrieving revision 1.30
|
|
retrieving revision 1.31
|
|
diff -u -r1.30 -r1.31
|
|
--- procfs_vnops.c 1997/08/02 14:32:20 1.30
|
|
+++ procfs_vnops.c 1997/08/12 04:34:30 1.31
|
|
@@ -36,7 +36,7 @@
|
|
*
|
|
* @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
|
|
*
|
|
- * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
+ * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
*/
|
|
|
|
/*
|
|
@@ -127,16 +127,21 @@
|
|
} */ *ap;
|
|
{
|
|
struct pfsnode *pfs = VTOPFS(ap->a_vp);
|
|
+ struct proc *p1 = ap->a_p, *p2 = PFIND(pfs->pfs_pid);
|
|
+
|
|
+ if (p2 == NULL)
|
|
+ return ENOENT;
|
|
|
|
switch (pfs->pfs_type) {
|
|
case Pmem:
|
|
- if (PFIND(pfs->pfs_pid) == 0)
|
|
- return (ENOENT); /* was ESRCH, jsp */
|
|
-
|
|
if ((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL) ||
|
|
(pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))
|
|
return (EBUSY);
|
|
|
|
+ if (!CHECKIO(p1, p2) &&
|
|
+ (p1->p_cred->pc_ucred->cr_gid != KMEM_GROUP))
|
|
+ return EPERM;
|
|
+
|
|
if (ap->a_mode & FWRITE)
|
|
pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
|
|
|
|
@@ -194,7 +199,6 @@
|
|
struct proc *a_p;
|
|
} */ *ap;
|
|
{
|
|
-
|
|
return (ENOTTY);
|
|
}
|
|
|
|
Index: procfs_fpregs.c
|
|
===================================================================
|
|
RCS file: /home/cvsup/freebsd/CVS/src/sys/miscfs/procfs/procfs_fpregs.c,v
|
|
retrieving revision 1.7
|
|
retrieving revision 1.8
|
|
diff -u -r1.7 -r1.8
|
|
--- procfs_fpregs.c 1997/08/02 14:32:11 1.7
|
|
+++ procfs_fpregs.c 1997/08/12 05:23:51 1.8
|
|
@@ -37,7 +37,7 @@
|
|
* @(#)procfs_fpregs.c 8.2 (Berkeley) 6/15/94
|
|
*
|
|
* From:
|
|
- * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
+ * $Id: FreeBSD-SA-97:04.procfs.asc,v 1.1 2001/09/02 00:04:38 kris Exp $
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
@@ -60,6 +60,8 @@
|
|
char *kv;
|
|
int kl;
|
|
|
|
+ if (!CHECKIO(curp, p))
|
|
+ return EPERM;
|
|
kl = sizeof(r);
|
|
kv = (char *) &r;
|
|
|
|
(These patches can also be found on
|
|
ftp://freebsd.org/pub/CERT/patches/SA-97:04/)
|
|
|
|
VI. Thanks
|
|
|
|
This problem was brought to light by Brian Mitchell
|
|
<brian@firehouse.net>
|
|
|
|
=============================================================================
|
|
FreeBSD, Inc.
|
|
|
|
Web Site: http://www.freebsd.org/
|
|
Confidential contacts: security-officer@freebsd.org
|
|
PGP Key: ftp://freebsd.org/pub/CERT/public_key.asc
|
|
Security notifications: security-notifications@freebsd.org
|
|
Security public discussion: security@freebsd.org
|
|
|
|
Notice: Any patches in this document may not apply cleanly due to
|
|
modifications caused by digital signature or mailer software.
|
|
Please reference the URL listed at the top of this document
|
|
for original copies of all patches if necessary.
|
|
=============================================================================
|
|
|
|
-----BEGIN PGP SIGNATURE-----
|
|
Version: 2.6.2
|
|
|
|
iQCVAwUBNAMWLFUuHi5z0oilAQHmrQQAoXR/BUliLCJgtDx/tG4lSNMpY2+wYWtw
|
|
PNiPjLfHHbA2yOXoJxv5ANw0Z6zeovCP1rHTKbG0vGNQe45d34kC+qY1hSKhYxjV
|
|
BGeEKzCUyfGn0ovrfWjmW6FL3n2Kq76yJbhR5tiev5vaM9+kvWKs8aK5c1maAEOv
|
|
PxYm/nzJg04=
|
|
=aC0v
|
|
-----END PGP SIGNATURE-----
|