[OpenAFS-announce] OpenAFS Security Advisory 2013-0001

Simon Wilkinson openafs-info@openafs.org
Mon, 4 Mar 2013 14:49:01 +0000


--Apple-Mail=_B9D5DBC4-1F8B-4407-B81A-6C4C386A429A
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=us-ascii

Topic: Buffer overflows in OpenAFS fileserver (CVE-2013-1794)

Issued:		4 March 2013
Last Updated:	4 March 2013
Affected:	OpenAFS servers before version 1.6.2

An attacker with the ability to manipulate AFS directory ACLs may crash the
fileserver hosting that volume. In addition, once a corrupt ACL is placed
on a fileserver, its existence may crash client utilities manipulating ACLs
on that server.

SUMMARY
=======

By carefully crafting an ACL entry an attacker may overflow fixed length 
buffers within the OpenAFS fileserver, crashing the fileserver, and 
potentially permitting the execution of arbitrary code. To perform the
exploit, the attacker must already have permissions to create ACLs on the
fileserver in question.

Once such an ACL is present on a fileserver, client utilities such as 'fs'
which manipulate ACLs, may be crashed when they attempt to read or modify
the ACL.

IMPACT
======

An authenticated attacker may crash, or run arbitrary code, on an OpenAFS 
fileserver, or a client connected to such a server

AFFECTED SOFTWARE
=================

All releases of OpenAFS prior to 1.6.2

FIXES
=====

The OpenAFS project recommends that administrators upgrade to OpenAFS
1.6.2 or later.

For those sites unable, or unwilling, to upgrade patches to resolve
this issue are included below. Patches are provided for both OpenAFS
1.6.1 and OpenAFS 1.4.14.1

The latest stable OpenAFS release is always available from
http://www.openafs.org/release/latest.html

This announcement, and code patches related to it, may be found on the
OpenAFS security advisory page at

    http://www.openafs.org/security/

ACKNOWLEDGEMENTS
================

This issue was identified, and the fix provided, by Nickolai Zeldovich


--Apple-Mail=_B9D5DBC4-1F8B-4407-B81A-6C4C386A429A
Content-Disposition: attachment;
	filename=openafs-sa-2013-0001-1_4_14_1.patch
Content-Type: application/octet-stream;
	name="openafs-sa-2013-0001-1_4_14_1.patch"
Content-Transfer-Encoding: 7bit

diff --git a/src/libacl/aclprocs.c b/src/libacl/aclprocs.c
index f294d09..5a1dbdc 100644
--- a/src/libacl/aclprocs.c
+++ b/src/libacl/aclprocs.c
@@ -23,6 +23,7 @@
 #else
 #include <netinet/in.h>
 #endif
+#include <limits.h>
 #include <string.h>
 #include <rx/xdr.h>
 #include <rx/rx.h>
@@ -247,7 +248,7 @@ acl_Internalize(elist, acl)
 
     if (sscanf(elist, "%d\n%d\n", &p, &n) != 2)
 	return -1;
-    if (p + n > ACL_MAXENTRIES)
+    if (p < 0 || n < 0 || p > INT_MAX - n || p + n > ACL_MAXENTRIES)
 	return (-1);
     acl_NewACL(p + n, acl);
     (*acl)->total = p + n;
@@ -272,7 +273,7 @@ acl_Internalize(elist, acl)
     nextc++;			/* now at the beginning of the entry list */
     for (i = 0; i < (*acl)->positive; i++) {
 	int k;
-	if (sscanf(nextc, "%s\t%d\n", lnames.namelist_val[i], &k) != 2) {
+	if (sscanf(nextc, "%63s\t%d\n", lnames.namelist_val[i], &k) != 2) {
 	    free(lnames.namelist_val);
 	    return (-1);
 	}
@@ -284,7 +285,7 @@ acl_Internalize(elist, acl)
     for (i = (*acl)->total - 1; i >= (*acl)->total - (*acl)->negative;
 	 i--, j++) {
 	if (sscanf
-	    (nextc, "%s\t%d\n", lnames.namelist_val[j],
+	    (nextc, "%63s\t%d\n", lnames.namelist_val[j],
 	     &((*acl)->entries[j].rights)) != 2) {
 	    free(lnames.namelist_val);
 	    return (-1);
diff --git a/src/libadmin/client/afs_clientAdmin.c b/src/libadmin/client/afs_clientAdmin.c
index a228d0a..ae7b387 100644
--- a/src/libadmin/client/afs_clientAdmin.c
+++ b/src/libadmin/client/afs_clientAdmin.c
@@ -1530,7 +1530,7 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
      */
 
     is_dfs =
-	sscanf(old_acl_string, "%d dfs:%d %s", &cur_acl.nplus, &cur_acl.dfs,
+	sscanf(old_acl_string, "%d dfs:%d %1024s", &cur_acl.nplus, &cur_acl.dfs,
 	       cur_acl.cell);
     ptr = strchr(old_acl_string, '\n');
     ptr++;
@@ -1555,7 +1555,7 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
      */
 
     for (i = 0; i < (cur_acl.nplus + cur_acl.nminus); i++) {
-	sscanf(ptr, "%s%d\n", cur_user, &cur_user_acl);
+	sscanf(ptr, "%63s%d\n", cur_user, &cur_user_acl);
 	/*
 	 * Skip the entry for the user we are replacing/adding
 	 */
diff --git a/src/venus/fs.c b/src/venus/fs.c
index fb4f4f1..7b4a992 100644
--- a/src/venus/fs.c
+++ b/src/venus/fs.c
@@ -561,7 +561,7 @@ EmptyAcl(char *astr)
     tp->nplus = tp->nminus = 0;
     tp->pluslist = tp->minuslist = 0;
     tp->dfs = 0;
-    sscanf(astr, "%d dfs:%d %s", &junk, &tp->dfs, tp->cell);
+    sscanf(astr, "%d dfs:%d %1024s", &junk, &tp->dfs, tp->cell);
     return tp;
 }
 
@@ -576,7 +576,7 @@ ParseAcl(char *astr)
     ta = (struct Acl *)malloc(sizeof(struct Acl));
     assert(ta);
     ta->dfs = 0;
-    sscanf(astr, "%d dfs:%d %s", &ta->nplus, &ta->dfs, ta->cell);
+    sscanf(astr, "%d dfs:%d %1024s", &ta->nplus, &ta->dfs, ta->cell);
     astr = SkipLine(astr);
     sscanf(astr, "%d", &ta->nminus);
     astr = SkipLine(astr);
@@ -587,7 +587,7 @@ ParseAcl(char *astr)
     last = 0;
     first = 0;
     for (i = 0; i < nplus; i++) {
-	sscanf(astr, "%100s %d", tname, &trights);
+	sscanf(astr, "%99s %d", tname, &trights);
 	astr = SkipLine(astr);
 	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
 	assert(tl);
@@ -605,7 +605,7 @@ ParseAcl(char *astr)
     last = 0;
     first = 0;
     for (i = 0; i < nminus; i++) {
-	sscanf(astr, "%100s %d", tname, &trights);
+	sscanf(astr, "%99s %d", tname, &trights);
 	astr = SkipLine(astr);
 	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
 	assert(tl);

--Apple-Mail=_B9D5DBC4-1F8B-4407-B81A-6C4C386A429A
Content-Disposition: attachment;
	filename=openafs-sa-2013-0001.patch
Content-Type: application/octet-stream;
	name="openafs-sa-2013-0001.patch"
Content-Transfer-Encoding: 7bit

diff --git a/src/libacl/aclprocs.c b/src/libacl/aclprocs.c
index 106dfe3..72bf8ae 100644
--- a/src/libacl/aclprocs.c
+++ b/src/libacl/aclprocs.c
@@ -23,13 +23,13 @@
 #else
 #include <netinet/in.h>
 #endif
+#include <limits.h>
 #include <string.h>
 #include <rx/xdr.h>
 #include <rx/rx.h>
 #include <afs/ptclient.h>
 #include <afs/ptuser.h>
 #include "acl.h"
-
 #ifdef AFS_PTHREAD_ENV
 #include <assert.h>
 #include <pthread.h>
@@ -251,7 +251,7 @@ acl_Internalize_pr(int (*func)(namelist *names, idlist *ids), char *elist, struc
 
     if (sscanf(elist, "%d\n%d\n", &p, &n) != 2)
 	return -1;
-    if (p + n > ACL_MAXENTRIES)
+    if (p < 0 || n < 0 || p > INT_MAX - n || p + n > ACL_MAXENTRIES)
 	return (-1);
     acl_NewACL(p + n, acl);
     (*acl)->total = p + n;
@@ -276,7 +276,7 @@ acl_Internalize_pr(int (*func)(namelist *names, idlist *ids), char *elist, struc
     nextc++;			/* now at the beginning of the entry list */
     for (i = 0; i < (*acl)->positive; i++) {
 	int k;
-	if (sscanf(nextc, "%s\t%d\n", lnames.namelist_val[i], &k) != 2) {
+	if (sscanf(nextc, "%63s\t%d\n", lnames.namelist_val[i], &k) != 2) {
 	    free(lnames.namelist_val);
 	    return (-1);
 	}
@@ -288,7 +288,7 @@ acl_Internalize_pr(int (*func)(namelist *names, idlist *ids), char *elist, struc
     for (i = (*acl)->total - 1; i >= (*acl)->total - (*acl)->negative;
 	 i--, j++) {
 	if (sscanf
-	    (nextc, "%s\t%d\n", lnames.namelist_val[j],
+	    (nextc, "%63s\t%d\n", lnames.namelist_val[j],
 	     &((*acl)->entries[j].rights)) != 2) {
 	    free(lnames.namelist_val);
 	    return (-1);
diff --git a/src/libadmin/client/afs_clientAdmin.c b/src/libadmin/client/afs_clientAdmin.c
index 3f50786..35dbd6c 100644
--- a/src/libadmin/client/afs_clientAdmin.c
+++ b/src/libadmin/client/afs_clientAdmin.c
@@ -1542,7 +1542,7 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
      */
 
     is_dfs =
-	sscanf(old_acl_string, "%d dfs:%d %s", &cur_acl.nplus, &cur_acl.dfs,
+	sscanf(old_acl_string, "%d dfs:%d %1024s", &cur_acl.nplus, &cur_acl.dfs,
 	       cur_acl.cell);
     ptr = strchr(old_acl_string, '\n');
     ptr++;
@@ -1567,7 +1567,7 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
      */
 
     for (i = 0; i < (cur_acl.nplus + cur_acl.nminus); i++) {
-	sscanf(ptr, "%s%d\n", cur_user, &cur_user_acl);
+	sscanf(ptr, "%63s%d\n", cur_user, &cur_user_acl);
 	/*
 	 * Skip the entry for the user we are replacing/adding
 	 */
iff --git a/src/venus/fs.c b/src/venus/fs.c
index 5ffa27b..02f7cd5 100644
--- a/src/venus/fs.c
+++ b/src/venus/fs.c
@@ -561,7 +561,7 @@ EmptyAcl(char *astr)
     tp->nplus = tp->nminus = 0;
     tp->pluslist = tp->minuslist = 0;
     tp->dfs = 0;
-    sscanf(astr, "%d dfs:%d %s", &junk, &tp->dfs, tp->cell);
+    sscanf(astr, "%d dfs:%d %1024s", &junk, &tp->dfs, tp->cell);
     return tp;
 }
 
@@ -576,7 +576,7 @@ ParseAcl(char *astr)
     ta = (struct Acl *)malloc(sizeof(struct Acl));
     assert(ta);
     ta->dfs = 0;
-    sscanf(astr, "%d dfs:%d %s", &ta->nplus, &ta->dfs, ta->cell);
+    sscanf(astr, "%d dfs:%d %1024s", &ta->nplus, &ta->dfs, ta->cell);
     astr = SkipLine(astr);
     sscanf(astr, "%d", &ta->nminus);
     astr = SkipLine(astr);
@@ -587,7 +587,7 @@ ParseAcl(char *astr)
     last = 0;
     first = 0;
     for (i = 0; i < nplus; i++) {
-	sscanf(astr, "%100s %d", tname, &trights);
+	sscanf(astr, "%99s %d", tname, &trights);
 	astr = SkipLine(astr);
 	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
 	assert(tl);
@@ -605,7 +605,7 @@ ParseAcl(char *astr)
     last = 0;
     first = 0;
     for (i = 0; i < nminus; i++) {
-	sscanf(astr, "%100s %d", tname, &trights);
+	sscanf(astr, "%99s %d", tname, &trights);
 	astr = SkipLine(astr);
 	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
 	assert(tl);


--Apple-Mail=_B9D5DBC4-1F8B-4407-B81A-6C4C386A429A--