[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[SRM] DoS fix for openafs in stable and oldstable



The latest release of OpenAFS has a fix for a possible DoS attack against
the OpenAFS client module.  This is an additional fix for the problem
fixed in CVE-2009-1250.  I think it's too minor to warrant a DSA (and I
haven't gotten any reply from two messages to the security team about it),
but I'd like to fix it in the stable and oldstable releases.  The fix went
into unstable with 1.4.11~pre3+dfsg-1.

Here is the patch against lenny.  The patch against etch is identical.  Do
I have approval to upload to stable-proposed-updates and
oldstable-proposed-updates?

diff --git a/debian/changelog b/debian/changelog
index 20a72eb..6a8bed8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+openafs (1.4.7.dfsg1-6+lenny2) UNRELEASED; urgency=low
+
+  * Apply upstream patch to avoid converting more negative errors into
+    invalid kernel memory pointers.
+
+ -- Russ Allbery <rra@debian.org>  Mon, 06 Jul 2009 19:27:22 -0700
+
 openafs (1.4.7.dfsg1-6+lenny1) stable-security; urgency=high
 
   * Apply upstream security patches from 1.4.9:
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 7a0af65..ed4354e 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -56,6 +56,22 @@ RCSID
 extern struct vcache *afs_globalVp;
 
 
+
+/* This function converts a positive error code from AFS into a negative
+ * code suitable for passing into the Linux VFS layer. It checks that the
+ * error code is within the permissable bounds for the ERR_PTR mechanism.
+ *
+ * _All_ error codes which come from the AFS layer should be passed through
+ * this function before being returned to the kernel.
+ */
+
+static inline int afs_convert_code(int code) {
+    if ((code >= 0) && (code <= MAX_ERRNO))
+	return -code;
+    else
+	return -EIO;
+}
+
 static ssize_t
 afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
 {
@@ -75,7 +91,7 @@ afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
 	code = afs_VerifyVCache(vcp, &treq);
 
     if (code)
-	code = -code;
+	code = afs_convert_code(code);
     else {
 	    osi_FlushPages(vcp, credp);	/* ensure stale pages are gone */
 	    AFS_GUNLOCK();
@@ -125,7 +141,7 @@ afs_linux_write(struct file *fp, const char *buf, size_t count, loff_t * offp)
     afs_FakeOpen(vcp);
     ReleaseWriteLock(&vcp->lock);
     if (code)
-	code = -code;
+	code = afs_convert_code(code);
     else {
 	    AFS_GUNLOCK();
 #ifdef DO_SYNC_READ
@@ -180,19 +196,25 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
 
     code = afs_InitReq(&treq, credp);
     crfree(credp);
-    if (code)
+    if (code) {
+	code = afs_convert_code(code);
 	goto out1;
+    }
 
     afs_InitFakeStat(&fakestat);
     code = afs_EvalFakeStat(&avc, &fakestat, &treq);
-    if (code)
+    if (code) {
+	code = afs_convert_code(code);
 	goto out;
+    }
 
     /* update the cache entry */
   tagain:
     code = afs_VerifyVCache(avc, &treq);
-    if (code)
+    if (code) {
+	code = afs_convert_code(code);
 	goto out;
+    }
 
     /* get a reference to the entire directory */
     tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &tlen, 1);
@@ -373,7 +395,7 @@ out:
     return code;
 
 out_err:
-    code = -code;
+    code = afs_convert_code(code);
     goto out;
 }
 
@@ -395,7 +417,7 @@ afs_linux_open(struct inode *ip, struct file *fp)
 #endif
 
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 static int
@@ -416,7 +438,7 @@ afs_linux_release(struct inode *ip, struct file *fp)
 #endif
 
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 static int
@@ -440,7 +462,7 @@ afs_linux_fsync(struct file *fp, struct dentry *dp)
     unlock_kernel();
 #endif
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 
 }
 
@@ -500,7 +522,7 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
     flp->fl_end = flock.l_start + flock.l_len;
 
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 
 }
 
@@ -599,7 +621,7 @@ out:
     AFS_GUNLOCK();
 
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 #if !defined(AFS_LINUX24_ENV)
@@ -756,7 +778,7 @@ afs_linux_revalidate(struct dentry *dp)
 #endif
     crfree(credp);
 
-    return -code;
+    return afs_convert_code(code);
 }
 
 #if defined(AFS_LINUX26_ENV)
@@ -981,7 +1003,7 @@ afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
     unlock_kernel();
 #endif
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 /* afs_linux_lookup */
@@ -1055,14 +1077,12 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
     if (code == ENOENT)
 	return ERR_PTR(0);
-    else if ((code >= 0) && (code <= MAX_ERRNO))
-	return ERR_PTR(-code);
-    else 
-	return ERR_PTR(-EIO);
+    else
+	return ERR_PTR(afs_convert_code(code));
 #else
     if (code == ENOENT)
 	code = 0;
-    return -code;
+    return afs_convert_code(code);
 #endif
 }
 
@@ -1084,7 +1104,7 @@ afs_linux_link(struct dentry *olddp, struct inode *dip, struct dentry *newdp)
 
     AFS_GUNLOCK();
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 static int
@@ -1164,7 +1184,7 @@ out:
     unlock_kernel();
 #endif
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 
@@ -1186,7 +1206,7 @@ afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target)
     code = afs_symlink(VTOAFS(dip), name, &vattr, target, credp);
     AFS_GUNLOCK();
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 static int
@@ -1223,7 +1243,7 @@ afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
     unlock_kernel();
 #endif
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 static int
@@ -1252,7 +1272,7 @@ afs_linux_rmdir(struct inode *dip, struct dentry *dp)
     }
 
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 
@@ -1304,7 +1324,7 @@ afs_linux_rename(struct inode *oldip, struct dentry *olddp,
 #endif
 
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 
@@ -1327,7 +1347,7 @@ afs_linux_ireadlink(struct inode *ip, char *target, int maxlen, uio_seg_t seg)
     if (!code)
 	return maxlen - tuio.uio_resid;
     else
-	return -code;
+	return afs_convert_code(code);
 }
 
 #if !defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
@@ -1506,7 +1526,7 @@ afs_linux_readpage(struct file *fp, struct page *pp)
     }
 
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 
@@ -1549,7 +1569,7 @@ afs_linux_writepage_sync(struct inode *ip, struct page *pp,
 	    code = afs_DoPartialWrite(vcp, &treq);
 	ReleaseWriteLock(&vcp->lock);
     }
-    code = code ? -code : count - tuio.uio_resid;
+    code = code ? afs_convert_code(code) : count - tuio.uio_resid;
 
     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
 	       ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
@@ -1654,7 +1674,7 @@ afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset,
 	ReleaseWriteLock(&vcp->lock);
     }
 
-    code = code ? -code : count - tuio.uio_resid;
+    code = code ? afs_convert_code(code) : count - tuio.uio_resid;
     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
 	       ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
 	       ICL_TYPE_INT32, code);
@@ -1692,7 +1712,7 @@ afs_linux_permission(struct inode *ip, int mode)
 
     AFS_GUNLOCK();
     crfree(credp);
-    return -code;
+    return afs_convert_code(code);
 }
 
 #if defined(AFS_LINUX24_ENV)

-- 
Russ Allbery (rra@debian.org)               <http://www.eyrie.org/~eagle/>


Reply to: