aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfsctl.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2009-04-23 19:33:18 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-04-28 13:54:30 -0400
commit261758b5c3dfeac73ca364c47ed538f5ce4250ee (patch)
treeb5d8a8ec58eba1f400b3b5d4fbe222cdeda39d28 /fs/nfsd/nfsctl.c
parent3d72ab8fdd44c872633b210dd1a4afd2910d0bbb (diff)
NFSD: Stricter buffer size checking in write_versions()
While it's not likely today that there are enough NFS versions to overflow the output buffer in write_versions(), we should be more careful about detecting the end of the buffer. The number of NFS versions will only increase as NFSv4 minor versions are added. Note that this API doesn't behave the same as portlist. Here we attempt to display as many versions as will fit in the buffer, and do not provide any indication that an overflow would have occurred. I don't have any good rationale for that. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/nfsd/nfsctl.c')
-rw-r--r--fs/nfsd/nfsctl.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index c4843467cfd4..a152694e016e 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -793,7 +793,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
793{ 793{
794 char *mesg = buf; 794 char *mesg = buf;
795 char *vers, *minorp, sign; 795 char *vers, *minorp, sign;
796 int len, num; 796 int len, num, remaining;
797 unsigned minor; 797 unsigned minor;
798 ssize_t tlen = 0; 798 ssize_t tlen = 0;
799 char *sep; 799 char *sep;
@@ -840,32 +840,50 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
840 } 840 }
841 next: 841 next:
842 vers += len + 1; 842 vers += len + 1;
843 tlen += len;
844 } while ((len = qword_get(&mesg, vers, size)) > 0); 843 } while ((len = qword_get(&mesg, vers, size)) > 0);
845 /* If all get turned off, turn them back on, as 844 /* If all get turned off, turn them back on, as
846 * having no versions is BAD 845 * having no versions is BAD
847 */ 846 */
848 nfsd_reset_versions(); 847 nfsd_reset_versions();
849 } 848 }
849
850 /* Now write current state into reply buffer */ 850 /* Now write current state into reply buffer */
851 len = 0; 851 len = 0;
852 sep = ""; 852 sep = "";
853 remaining = SIMPLE_TRANSACTION_LIMIT;
853 for (num=2 ; num <= 4 ; num++) 854 for (num=2 ; num <= 4 ; num++)
854 if (nfsd_vers(num, NFSD_AVAIL)) { 855 if (nfsd_vers(num, NFSD_AVAIL)) {
855 len += sprintf(buf+len, "%s%c%d", sep, 856 len = snprintf(buf, remaining, "%s%c%d", sep,
856 nfsd_vers(num, NFSD_TEST)?'+':'-', 857 nfsd_vers(num, NFSD_TEST)?'+':'-',
857 num); 858 num);
858 sep = " "; 859 sep = " ";
860
861 if (len > remaining)
862 break;
863 remaining -= len;
864 buf += len;
865 tlen += len;
859 } 866 }
860 if (nfsd_vers(4, NFSD_AVAIL)) 867 if (nfsd_vers(4, NFSD_AVAIL))
861 for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION; minor++) 868 for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION;
862 len += sprintf(buf+len, " %c4.%u", 869 minor++) {
870 len = snprintf(buf, remaining, " %c4.%u",
863 (nfsd_vers(4, NFSD_TEST) && 871 (nfsd_vers(4, NFSD_TEST) &&
864 nfsd_minorversion(minor, NFSD_TEST)) ? 872 nfsd_minorversion(minor, NFSD_TEST)) ?
865 '+' : '-', 873 '+' : '-',
866 minor); 874 minor);
867 len += sprintf(buf+len, "\n"); 875
868 return len; 876 if (len > remaining)
877 break;
878 remaining -= len;
879 buf += len;
880 tlen += len;
881 }
882
883 len = snprintf(buf, remaining, "\n");
884 if (len > remaining)
885 return -EINVAL;
886 return tlen + len;
869} 887}
870 888
871/** 889/**