aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Harkes <jaharkes@cs.cmu.edu>2019-07-16 19:28:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-07-16 22:23:23 -0400
commit6e51f8aa76b67d0a6eb168fd41a81e8478ae07a9 (patch)
tree4eaac753b2f94feeb721880e0c5445f071aa384e
parent02551c23bcd85f0c68a8259c7b953d49d44f86af (diff)
coda: potential buffer overflow in coda_psdev_write()
Add checks to make sure the downcall message we got from the Coda cache manager is large enough to contain the data it is supposed to have. i.e. when we get a CODA_ZAPDIR we can access &out->coda_zapdir.CodaFid. Link: http://lkml.kernel.org/r/894fb6b250add09e4e3935f14649f21284a5cb18.1558117389.git.jaharkes@cs.cmu.edu Signed-off-by: Jan Harkes <jaharkes@cs.cmu.edu> Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Colin Ian King <colin.king@canonical.com> Cc: David Howells <dhowells@redhat.com> Cc: Fabian Frederick <fabf@skynet.be> Cc: Mikko Rapeli <mikko.rapeli@iki.fi> Cc: Sam Protsenko <semen.protsenko@linaro.org> Cc: Yann Droneaud <ydroneaud@opteya.com> Cc: Zhouyang Jia <jiazhouyang09@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/coda/psdev.c8
-rw-r--r--fs/coda/upcall.c34
-rw-r--r--include/linux/coda_psdev.h3
3 files changed, 41 insertions, 4 deletions
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 241f7e04ad04..b4da2812499e 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -100,8 +100,12 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
100 ssize_t retval = 0, count = 0; 100 ssize_t retval = 0, count = 0;
101 int error; 101 int error;
102 102
103 /* make sure there is enough to copy out the (opcode, unique) values */
104 if (nbytes < (2 * sizeof(u_int32_t)))
105 return -EINVAL;
106
103 /* Peek at the opcode, uniquefier */ 107 /* Peek at the opcode, uniquefier */
104 if (copy_from_user(&hdr, buf, 2 * sizeof(u_long))) 108 if (copy_from_user(&hdr, buf, 2 * sizeof(u_int32_t)))
105 return -EFAULT; 109 return -EFAULT;
106 110
107 if (DOWNCALL(hdr.opcode)) { 111 if (DOWNCALL(hdr.opcode)) {
@@ -127,7 +131,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
127 } 131 }
128 132
129 /* what downcall errors does Venus handle ? */ 133 /* what downcall errors does Venus handle ? */
130 error = coda_downcall(vcp, hdr.opcode, dcbuf); 134 error = coda_downcall(vcp, hdr.opcode, dcbuf, nbytes);
131 135
132 CODA_FREE(dcbuf, nbytes); 136 CODA_FREE(dcbuf, nbytes);
133 if (error) { 137 if (error) {
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 1175a1722411..cf1e662681a5 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -804,12 +804,44 @@ exit:
804 * 804 *
805 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */ 805 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
806 806
807int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out) 807int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out,
808 size_t nbytes)
808{ 809{
809 struct inode *inode = NULL; 810 struct inode *inode = NULL;
810 struct CodaFid *fid = NULL, *newfid; 811 struct CodaFid *fid = NULL, *newfid;
811 struct super_block *sb; 812 struct super_block *sb;
812 813
814 /*
815 * Make sure we have received enough data from the cache
816 * manager to populate the necessary fields in the buffer
817 */
818 switch (opcode) {
819 case CODA_PURGEUSER:
820 if (nbytes < sizeof(struct coda_purgeuser_out))
821 return -EINVAL;
822 break;
823
824 case CODA_ZAPDIR:
825 if (nbytes < sizeof(struct coda_zapdir_out))
826 return -EINVAL;
827 break;
828
829 case CODA_ZAPFILE:
830 if (nbytes < sizeof(struct coda_zapfile_out))
831 return -EINVAL;
832 break;
833
834 case CODA_PURGEFID:
835 if (nbytes < sizeof(struct coda_purgefid_out))
836 return -EINVAL;
837 break;
838
839 case CODA_REPLACE:
840 if (nbytes < sizeof(struct coda_replace_out))
841 return -EINVAL;
842 break;
843 }
844
813 /* Handle invalidation requests. */ 845 /* Handle invalidation requests. */
814 mutex_lock(&vcp->vc_mutex); 846 mutex_lock(&vcp->vc_mutex);
815 sb = vcp->vc_sb; 847 sb = vcp->vc_sb;
diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
index 57d2b2faf6a3..d1672fd5e638 100644
--- a/include/linux/coda_psdev.h
+++ b/include/linux/coda_psdev.h
@@ -71,7 +71,8 @@ int venus_symlink(struct super_block *sb, struct CodaFid *fid,
71int venus_access(struct super_block *sb, struct CodaFid *fid, int mask); 71int venus_access(struct super_block *sb, struct CodaFid *fid, int mask);
72int venus_pioctl(struct super_block *sb, struct CodaFid *fid, 72int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
73 unsigned int cmd, struct PioctlData *data); 73 unsigned int cmd, struct PioctlData *data);
74int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out); 74int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out,
75 size_t nbytes);
75int venus_fsync(struct super_block *sb, struct CodaFid *fid); 76int venus_fsync(struct super_block *sb, struct CodaFid *fid);
76int venus_statfs(struct dentry *dentry, struct kstatfs *sfs); 77int venus_statfs(struct dentry *dentry, struct kstatfs *sfs);
77 78