public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Thomas Hood <jdthood@mail.com>
To: linux-kernel@vger.kernel.org
Cc: Andreas Schwab <schwab@suse.de>
Subject: Re: [PATCH] Documentation for proc_file_read
Date: 03 Feb 2002 09:58:05 -0500	[thread overview]
Message-ID: <1012748288.809.22.camel@thanatos> (raw)

After further study I have revised the documentation
to fix some mistakes.

This patch also fixes some problems in the code. First,
the patch adds checks for buffer overruns.  (The
original code allows the user to return any number
as the number of bytes to copy to the user, even if
this would exceed procfs's and/or the user's buffer.)
Second, with *start==NULL, n is trimmed down to "count"
_prior_ to subtracting the offset.  (The original code
trims n down to count after subtracting the offset;
but this means that it could be copying up to count
many bytes near the very end of the buffer.)

Still just asking for criticism.

--
Thomas

--- linux-2.4.18-pre7_ORIG/fs/proc/generic.c	Fri Sep  7 13:53:59 2001
+++ linux-2.4.18-pre7/fs/proc/generic.c	Sun Feb  3 08:51:32 2002
@@ -65,55 +65,101 @@
 	{
 		count = MIN(PROC_BLOCK_SIZE, nbytes);
 
 		start = NULL;
 		if (dp->get_info) {
-			/*
-			 * Handle backwards compatibility with the old net
-			 * routines.
-			 */
+			/* Handle old net routines */
 			n = dp->get_info(page, &start, *ppos, count);
 			if (n < count)
 				eof = 1;
 		} else if (dp->read_proc) {
+			/*
+			 * How to be a proc read function
+			 * ------------------------------
+			 * Prototype:
+			 *    int f(char *buffer, char **start, off_t offset,
+			 *          int count, int *peof, void *dat)
+			 *
+			 * Assume that the buffer is "count" bytes in size.
+			 *
+			 * If you know you have supplied all the data you
+			 * have, set *peof.
+			 *
+			 * You have three ways to return data:
+			 * 0) Leave *start = NULL.  (This is the default.)
+			 *    Put the data of the requested offset at that
+			 *    offset within the buffer.  Return the number (n)
+			 *    of bytes there are from the beginning of the
+			 *    buffer up to the last byte of data.  If the
+			 *    number of supplied bytes (= n - offset) is 
+			 *    greater than zero (and you didn't signal eof)
+			 *    you will be called again with the requested
+			 *    offset advanced by the number of bytes 
+			 *    absorbed.  This interface is useful for files
+			 *    no larger than the buffer.
+			 * 1) Set *start = a small value (less than buffer
+			 *    but greater than zero).
+			 *    Put the data of the requested offset at the
+			 *    beginning of the buffer.  Return the number of
+			 *    bytes of data placed there.  If this number is
+			 *    greater than zero (and you didn't signal eof),
+			 *    you will be called again with the requested
+			 *    offset advanced by *start.  This interface is
+			 *    useful when you have a large file consisting
+			 *    of a series of blocks which you want to count
+			 *    and return as wholes.
+			 *    (hack by Paul.Russell@rustcorp.com.au)
+			 * 2) Set *start = an address within the buffer.
+			 *    Put the data of the requested offset at *start.
+			 *    Return the number (n) of bytes of data placed
+			 *    there.  If this number is greater than zero
+			 *    (and you didn't signal eof) you will be called
+			 *    again with the requested offset advanced by
+			 *    the number of bytes absorbed.
+			 */
 			n = dp->read_proc(page, &start, *ppos,
 					  count, &eof, dp->data);
 		} else
 			break;
 
-		if (!start) {
-			/*
-			 * For proc files that are less than 4k
-			 */
+		if (n == 0)   /* end of file */
+			break;
+		if (n < 0) {  /* error */
+			if (retval == 0)
+				retval = n;
+			break;
+		}
+
+		if (start == NULL) {
 			start = page + *ppos;
+			if (n > PAGE_SIZE)
+				printk(KERN_ERR "proc_file_read: Buffer overflow!\n");
+			if (n > count)
+				n = count;
 			n -= *ppos;
 			if (n <= 0)
 				break;
+		} else if (start < page) {
+			if (n > PAGE_SIZE)
+				printk(KERN_ERR "proc_file_read: Buffer overflow!\n");
+			if (n > count)
+				printk(KERN_WARNING "proc_file_read: Read count exceeded\n");
+		} else /* start >= page */ {
+			if ((start - page + n) > PAGE_SIZE)
+				printk(KERN_ERR "proc_file_read: Buffer overflow!\n");
 			if (n > count)
 				n = count;
 		}
-		if (n == 0)
-			break;	/* End of file */
-		if (n < 0) {
-			if (retval == 0)
-				retval = n;
-			break;
-		}
 		
-		/* This is a hack to allow mangling of file pos independent
- 		 * of actual bytes read.  Simply place the data at page,
- 		 * return the bytes, and set `start' to the desired offset
- 		 * as an unsigned int. - Paul.Russell@rustcorp.com.au
-		 */
  		n -= copy_to_user(buf, start < page ? page : start, n);
 		if (n == 0) {
 			if (retval == 0)
 				retval = -EFAULT;
 			break;
 		}
 
-		*ppos += start < page ? (long)start : n; /* Move down the file */
+		*ppos += start < page ? (unsigned long)start : n;
 		nbytes -= n;
 		buf += n;
 		retval += n;
 	}
 	free_page((unsigned long) page);




             reply	other threads:[~2002-02-03 14:58 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-02-03 14:58 Thomas Hood [this message]
  -- strict thread matches above, loose matches on Subject: below --
2002-02-07  1:38 [PATCH] Documentation for proc_file_read Thomas Hood
2002-02-02 14:47 Thomas Hood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1012748288.809.22.camel@thanatos \
    --to=jdthood@mail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=schwab@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox